<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://goofyer.gitee.io/notes-on-computer-expertise/page/7/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/notes-on-computer-expertise/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/notes-on-computer-expertise/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/notes-on-computer-expertise/css/style.css">

  
    
<link rel="stylesheet" href="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/notes-on-computer-expertise/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/">Home</a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/notes-on-computer-expertise/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://goofyer.gitee.io/notes-on-computer-expertise"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-数据结构/数据结构" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/23/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" class="article-date">
  <time class="dt-published" datetime="2021-12-22T19:11:34.840Z" itemprop="datePublished">2021-12-23</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h1><h2 id="一、绪论"><a href="#一、绪论" class="headerlink" title="一、绪论"></a>一、绪论</h2><h3 id="1、什么是数据结构？"><a href="#1、什么是数据结构？" class="headerlink" title="1、什么是数据结构？"></a>1、什么是数据结构？</h3><p><img src="\数据结构\IMG_20201205_160610.jpg" alt="IMG_20201205_160610"></p>
<ul>
<li>数据结构包括逻辑结构，存储结构，还有数据的运算</li>
<li><p>1.1 为什么要学习数据结构</p>
<ul>
<li><p>电子计算机的主要用途</p>
<ul>
<li><p>早期</p>
<ul>
<li>数值计算</li>
</ul>
</li>
<li><p>现在</p>
<ul>
<li>非数值计算领域</li>
</ul>
</li>
</ul>
</li>
<li><p>数据结构的作用</p>
<ul>
<li><p>建立模型</p>
<ul>
<li>描述问题共性</li>
<li>分析问题过程</li>
</ul>
</li>
<li><p>构造求解算法</p>
<ul>
<li>描述问题求解方法</li>
<li>进行更为复杂的算法设计</li>
</ul>
</li>
<li><p>选择存储结构</p>
<ul>
<li>将问题设计的数据存储到计算机中</li>
<li>选择合理的存储结构</li>
</ul>
</li>
<li><p>编写程序</p>
<ul>
<li>提高编程技术</li>
</ul>
</li>
<li><p>测试</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>1.2学习数据结构用处</p>
<ul>
<li>计算机内数值运算依靠数学方程，而非数值运算依靠数据结构</li>
<li>同样的数据对象用不同的数据结构 运算效率可能有明显差异</li>
<li><p>程序设计的实质是对实际问题选择一个好的数据结构，加之设计一个好的算法。二好的算法取决于描述实际问题的数据结构</p>
<ul>
<li>算法+数据结构=程序</li>
</ul>
</li>
</ul>
</li>
<li><p>1.3 数据结构形成与发展</p>
</li>
<li><p>1.4数据结构地位</p>
<ul>
<li>数学 计算机硬件 计算机软件的核心</li>
</ul>
</li>
</ul>
<h3 id="子主题-5"><a href="#子主题-5" class="headerlink" title="子主题 5"></a>子主题 5</h3><ul>
<li><ul>
<li>数据结构的基本概念</li>
</ul>
</li>
<li><ul>
<li>基本概念与术语</li>
</ul>
</li>
<li><ul>
<li>数据</li>
</ul>
</li>
<li><ul>
<li>数据是信息的载体，是描述客观事物的符号的集合</li>
</ul>
</li>
<li><ul>
<li>数据对象</li>
</ul>
</li>
<li><ul>
<li>具有相同性质的数据元素的集合，是数据的一个子集</li>
</ul>
</li>
<li><ul>
<li>数据元素</li>
</ul>
</li>
<li><ul>
<li>数据的基本单元</li>
</ul>
</li>
<li><ul>
<li>数据项</li>
</ul>
</li>
<li><ul>
<li>构成数据元素的不可分割的最小单位</li>
</ul>
</li>
<li><ul>
<li>数据类型（结合+操作）</li>
</ul>
</li>
<li><ul>
<li>原子类型</li>
</ul>
</li>
<li><ul>
<li>结构类型</li>
</ul>
</li>
<li><ul>
<li>抽象数据类型ADT  </li>
</ul>
</li>
<li><ul>
<li>数据对象+数据关系+操作</li>
</ul>
</li>
<li><ul>
<li>一个数学模型以及定义在该模型是的一组操作</li>
</ul>
</li>
<li><ul>
<li>原子类型、固定聚合类型、可变聚合类型</li>
</ul>
</li>
<li><ul>
<li>结构：数据的相互关系</li>
</ul>
</li>
<li><ul>
<li>数据结构：相互之间存在一种或多种特定关系的数据元素的集合</li>
</ul>
</li>
<li><ul>
<li>三要素</li>
</ul>
</li>
<li><ul>
<li>逻辑结构</li>
</ul>
</li>
<li><ul>
<li>集合</li>
</ul>
</li>
<li><ul>
<li>线性结构</li>
</ul>
</li>
<li><ul>
<li>线性表、栈队列</li>
</ul>
</li>
<li><ul>
<li>非线性结构</li>
</ul>
</li>
<li><ul>
<li>树形结构</li>
</ul>
</li>
<li><ul>
<li>图形结构</li>
</ul>
</li>
<li><ul>
<li>存储结构</li>
</ul>
</li>
<li><ul>
<li>散列存储</li>
</ul>
</li>
<li><ul>
<li>索引存储</li>
</ul>
</li>
<li><ul>
<li>顺序存储</li>
</ul>
</li>
<li><ul>
<li>链式存储</li>
</ul>
</li>
<li><ul>
<li>数据的运算</li>
</ul>
</li>
<li><ul>
<li>运算包括定义与实现</li>
</ul>
</li>
<li><ul>
<li>定义</li>
</ul>
</li>
<li><ul>
<li>实现</li>
</ul>
</li>
<li><ul>
<li>算法与算法评价</li>
</ul>
</li>
<li><ul>
<li>算法的基本概念</li>
</ul>
</li>
<li><ul>
<li>算法</li>
</ul>
</li>
<li><ul>
<li>对特定问题的求解步骤的一种描述，他是指令的有限序列，其中每条指令由一个或多个操作</li>
</ul>
</li>
<li><ul>
<li>特性</li>
</ul>
</li>
<li><ul>
<li>有穷性</li>
</ul>
</li>
<li><ul>
<li>可行性</li>
</ul>
</li>
<li><ul>
<li>确定性</li>
</ul>
</li>
<li><ul>
<li>输入、输出</li>
</ul>
</li>
<li><ul>
<li>算法</li>
</ul>
</li>
<li><ul>
<li>解决问题的一种方法 一个过程</li>
</ul>
</li>
<li><ul>
<li>有穷  无穷</li>
</ul>
</li>
<li><ul>
<li>正确性</li>
</ul>
</li>
<li><ul>
<li>描述方法</li>
</ul>
</li>
<li><ul>
<li>程序</li>
</ul>
</li>
<li><ul>
<li>对算法的一种实现</li>
</ul>
</li>
<li><ul>
<li>算法效率的度量</li>
</ul>
</li>
<li><ul>
<li>正确性</li>
</ul>
</li>
<li><ul>
<li>算法应该正确解决求解问题</li>
</ul>
</li>
<li><ul>
<li>可读性</li>
</ul>
</li>
<li><ul>
<li>健壮性</li>
</ul>
</li>
<li><ul>
<li>效率与存储需求</li>
</ul>
</li>
<li><ul>
<li>时间复杂度</li>
</ul>
</li>
<li><ul>
<li>算法执行时间</li>
</ul>
</li>
<li><ul>
<li>语句的频度</li>
</ul>
</li>
<li><ul>
<li>这条语句可能重复执行的次数</li>
</ul>
</li>
<li><ul>
<li>T(n)  所有语句的频度之和</li>
</ul>
</li>
<li><ul>
<li>T(n)=O(f(n))  n趋于正无穷  同阶无穷大</li>
</ul>
</li>
<li><ul>
<li>最坏时间复杂度</li>
</ul>
</li>
<li><ul>
<li>加法规则</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>乘法规则</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>基本运算频道</li>
</ul>
</li>
<li><ul>
<li>O(1)  O(logn) O(n) O(nlogn) O(n^2) O(n^3) O(2^n) O(N!)  O(n^n)</li>
</ul>
</li>
<li><ul>
<li>空间复杂度</li>
</ul>
</li>
<li><ul>
<li>S(n)=O(g(n))</li>
</ul>
</li>
<li><ul>
<li>所需存储空间</li>
</ul>
</li>
<li><ul>
<li>除本身所用的指令常数变量输入外，还需要一些对数据进行操作的工作单位和存储为实现算法所需的一些信息的辅助空间</li>
</ul>
</li>
<li><ul>
<li>原地工作   O(1)</li>
</ul>
</li>
</ul>
<h3 id="2-基本概念"><a href="#2-基本概念" class="headerlink" title="2.基本概念"></a>2.基本概念</h3><ul>
<li><p>2.1 数据</p>
<ul>
<li>数据是信息的载体，是描述客观事物的数、字符，以及所有能输入到计算机中并被计算机程序识别和处理符号的集合，是计算机程序加工的素材‘</li>
<li><p>分类</p>
<ul>
<li>数值型数据</li>
<li>非数值型数据</li>
</ul>
</li>
</ul>
</li>
<li><p>2.2数据元素 data element</p>
<ul>
<li>数据的基本单位，计算机种作为一个整体考虑</li>
<li>一个数据元素可以由多个数据项dataitem组成</li>
<li>数据项是数据不可分割的最小标识单位</li>
</ul>
</li>
<li><p>2.3数据对象dataobject</p>
<ul>
<li>数据对象是具有相同性质的数据元素的集合</li>
<li><p>例子</p>
<ul>
<li><p>整数数据对象</p>
<ul>
<li>N={0,1,23,4,5}</li>
</ul>
</li>
<li><p>字母字符数据对象</p>
<ul>
<li>C={‘A’,’B’,’C’}</li>
</ul>
</li>
<li><p>学生成绩数据对象</p>
<ul>
<li>Cj={(‘101’,’a’,34),(‘102’,’b’,70)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>2.4数据结构datastructure</p>
<ul>
<li>数据结构是相互之间存在的一种或多种特定关系的数据元素的集合</li>
<li><p>结构</p>
<ul>
<li>数据元素存在某种关系</li>
</ul>
</li>
<li><p>数据结构=（数据元素和数据元素之间的关系）之和</p>
<ul>
<li><p>逻辑结构</p>
<ul>
<li><p>集合</p>
<ul>
<li>数据结构之间无特殊关系</li>
</ul>
</li>
<li><p>线性结构</p>
<ul>
<li>一对一</li>
</ul>
</li>
<li><p>树形结构</p>
<ul>
<li>一对多</li>
</ul>
</li>
<li><p>图形结构</p>
<ul>
<li>多对多</li>
</ul>
</li>
</ul>
</li>
<li><p>存储结构</p>
<ul>
<li>顺序存储结构</li>
<li>链式存储结构</li>
<li>索引存储结构</li>
<li>哈希存储结构</li>
</ul>
</li>
</ul>
</li>
<li><p>是数据结构形式定义</p>
<ul>
<li><p>二元组表示：dataStruture=（D，S）</p>
<ul>
<li>D 数据元素的有限级</li>
<li>S 该对象种所有数据成员之间关系的优先集合</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>2.5数据类型</p>
<ul>
<li>一个值的集合和定义在这个值集上的一组操作的总称</li>
<li><p>分类</p>
<ul>
<li><p>原子类型</p>
<ul>
<li>整形</li>
<li>实型</li>
<li>字符型</li>
</ul>
</li>
<li><p>结构类型</p>
<ul>
<li>数组</li>
<li>结构体</li>
<li>联合</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-抽象数据类型"><a href="#3-抽象数据类型" class="headerlink" title="3.抽象数据类型"></a>3.抽象数据类型</h3><ul>
<li>由用户定义，用以表示应用问题的数据模型</li>
<li>一个数据模型以及定义在此数据模型的一组操作</li>
<li>他与数据类型是一个概念，特征是与实现分离实行封装和信息隐蔽</li>
<li><p>描述方法</p>
<ul>
<li><p>（DSP）</p>
<ul>
<li>D 数据对象</li>
<li>S D的关系集</li>
<li>P D的基本操作集</li>
</ul>
</li>
<li><p>ADT抽象数据类型</p>
<ul>
<li>数据对象</li>
<li>数据关系</li>
<li>基本操作</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="4-算法及其分析"><a href="#4-算法及其分析" class="headerlink" title="4.算法及其分析"></a>4.算法及其分析</h3><ul>
<li><p>算法的定义</p>
<ul>
<li>对特定问题求解步骤的一种描述，是一个有穷的指令集，这些指令表示一个多个操作</li>
</ul>
</li>
<li><p>要素</p>
<ul>
<li><p>有穷性</p>
<ul>
<li>算法执行有限个步结束，时间有限</li>
</ul>
</li>
<li><p>确定性</p>
<ul>
<li>每步定义确切</li>
</ul>
</li>
<li><p>可行性</p>
<ul>
<li>算法描述的操作能通过有限次已经实现的基本运算实现</li>
</ul>
</li>
<li><p>输入</p>
</li>
<li>输出</li>
</ul>
</li>
<li><p>要求</p>
<ul>
<li><p>正确性</p>
<ul>
<li>不含有语法错误，对于各种合法输入都可以得到满足说明要求的结果</li>
</ul>
</li>
<li><p>可读性</p>
<ul>
<li>有较好的人机交互</li>
</ul>
</li>
<li><p>健壮性</p>
<ul>
<li>对输入的非法数据可以做出适当的响应</li>
</ul>
</li>
</ul>
</li>
<li><p>算法效率</p>
<ul>
<li><p>后期测试</p>
<ul>
<li>插入时间函数</li>
</ul>
</li>
<li><p>事前估计</p>
<ul>
<li>时间复杂度</li>
<li>空间复杂度</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="二：线性表"><a href="#二：线性表" class="headerlink" title="二：线性表"></a>二：线性表</h2><h3 id="1-线性表的定义"><a href="#1-线性表的定义" class="headerlink" title="1.线性表的定义"></a>1.线性表的定义</h3><ul>
<li><p>线性表的特点</p>
<ul>
<li>有限个数</li>
<li>逻辑上有顺序性</li>
<li>每个表元素都是单个元素</li>
<li>表元素类型皆相同</li>
<li>元素具有抽象性</li>
</ul>
</li>
<li><p>子主题 3</p>
<ul>
<li><h3 id="第一章-线性表"><a href="#第一章-线性表" class="headerlink" title="第一章  线性表"></a>第一章  线性表</h3></li>
<li><ul>
<li>线性表的定义与基本操作</li>
</ul>
</li>
<li><ul>
<li>逻辑结构：具有相同类型的n个元素的有限序列   L=(a1a2a3a4)</li>
</ul>
</li>
<li><ul>
<li>特点</li>
</ul>
</li>
<li><ul>
<li>有限</li>
</ul>
</li>
<li><ul>
<li>顺序性：元素有先后次序</li>
</ul>
</li>
<li><ul>
<li>元素是数据元素</li>
</ul>
</li>
<li><ul>
<li>每个元素的数据类型相同，有相同的存储空间</li>
</ul>
</li>
<li><ul>
<li>抽象性，只讨论元素间的一一关系，不考虑内容</li>
</ul>
</li>
<li><ul>
<li>逻辑结构，表示元素之间一对一相邻的关系</li>
</ul>
</li>
<li><ul>
<li>除第一与最后每个元素有且仅有一个直接后继</li>
</ul>
</li>
<li><ul>
<li>线性表的9中操作</li>
</ul>
</li>
<li><ul>
<li>InitList(&amp;L)</li>
</ul>
</li>
<li><ul>
<li>DestroyList(&amp;L)</li>
</ul>
</li>
<li><ul>
<li>LocateElem(L,e)</li>
</ul>
</li>
<li><ul>
<li>按值查找</li>
</ul>
</li>
<li><ul>
<li>GetElem(l,i)</li>
</ul>
</li>
<li><ul>
<li>按位查找</li>
</ul>
</li>
<li><ul>
<li>ListInser(&amp;L,i,e)</li>
</ul>
</li>
<li><ul>
<li>前插</li>
</ul>
</li>
<li><ul>
<li>bool ListInsert(LinkList&amp;L, int i, int e)//插入</li>
</ul>
</li>
<li>{</li>
<li>if (i<1 || i>L.length + 1)</li>
<li>return false;</li>
<li>if (i &gt;= 10)</li>
<li>return false;</li>
<li>for (auto j = L.length; j &gt;= i; j++)</li>
<li>L.data[j] = L.data[j - 1];</li>
<li>L.data[i - 1] = e;</li>
<li>L.length++;</li>
<li>return true;</li>
<li><p>}</p>
<ul>
<li><ul>
<li>时间复杂度：O(1) O(n)</li>
</ul>
</li>
<li></li>
<li><ul>
<li>listDelete(&amp;L,i,&amp;e)</li>
</ul>
</li>
<li></li>
<li><ul>
<li>bool ListDelete(LinkList&amp;L, int i, int&amp;e)//删除第i位元素</li>
</ul>
</li>
</ul>
</li>
<li><p>{</p>
<ul>
<li>if (i &lt; 1 || i &gt;= L.length)return false;</li>
<li>e = L.data[i - 1];</li>
<li><p>for (int i = 0; i &lt; L.length; i++)</p>
<ul>
<li>L.data[i - 1] = L.data[i];</li>
</ul>
</li>
<li><p>L.length—;</p>
</li>
<li>return true;</li>
</ul>
</li>
<li><p>}</p>
<ul>
<li><ul>
<li><p>PrintList(L)</p>
<ul>
<li><ul>
<li>Empty（L）</li>
</ul>
</li>
<li><ul>
<li>Length(L)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>线性表的顺序表示</li>
</ul>
</li>
<li><ul>
<li>顺序表的定义</li>
</ul>
</li>
<li><ul>
<li>线性表的顺序存储</li>
</ul>
</li>
<li><ul>
<li>一组地址连续存放的存储单元一次存放线性表的元素</li>
</ul>
</li>
<li><ul>
<li>数组实现顺序表</li>
</ul>
</li>
<li><ul>
<li>数组静态分配</li>
</ul>
</li>
<li><ul>
<li>struct LinkList</li>
</ul>
</li>
<li>{</li>
<li>int data[10000];//顺序表中的元素</li>
<li>int length;//当前长度</li>
<li>};</li>
<li>- </li>
<li><ul>
<li>数组动态分配</li>
</ul>
</li>
<li><ul>
<li>struct LinkList</li>
</ul>
</li>
<li>{</li>
<li>int *data;//顺序表中的元素</li>
<li>int length;//当前长度</li>
<li>};</li>
<li><ul>
<li>L.data = (int<em>)malloc(sizeof(int)</em>InitSize);</li>
</ul>
</li>
<li><ul>
<li>L.data = new int[InitSize];</li>
</ul>
</li>
<li><ul>
<li>特点</li>
</ul>
</li>
<li><ul>
<li>逻辑顺序与物理顺序相同</li>
</ul>
</li>
<li><ul>
<li>随机存储</li>
</ul>
</li>
<li><ul>
<li>顺序表的操作</li>
</ul>
</li>
<li><ul>
<li>LocateElem(L,e)</li>
</ul>
</li>
<li><ul>
<li>按值查找</li>
</ul>
</li>
<li><ul>
<li>GetElem(l,i)</li>
</ul>
</li>
<li><ul>
<li>按位查找</li>
</ul>
</li>
<li><ul>
<li>时间复杂度O(1)</li>
</ul>
</li>
<li><ul>
<li>ListInser(&amp;L,i,e)</li>
</ul>
</li>
<li><ul>
<li>前插</li>
</ul>
</li>
<li><ul>
<li>bool ListInsert(LinkList&amp;L, int i, int e)//插入</li>
</ul>
</li>
<li>{</li>
<li>if (i<1 || i>L.length + 1)</li>
<li>return false;</li>
<li>if (i &gt;= 10)</li>
<li>return false;</li>
<li>for (auto j = L.length; j &gt;= i; j++)</li>
<li>L.data[j] = L.data[j - 1];</li>
<li>L.data[i - 1] = e;</li>
<li>L.length++;</li>
<li>return true;</li>
<li><p>}</p>
<ul>
<li><ul>
<li>时间复杂度：O(1) O(n)</li>
</ul>
</li>
<li></li>
<li><ul>
<li>listDelete(&amp;L,i,&amp;e)</li>
</ul>
</li>
<li></li>
<li><ul>
<li>bool ListDelete(LinkList&amp;L, int i, int&amp;e)//删除第i位元素</li>
</ul>
</li>
</ul>
</li>
<li><p>{</p>
<ul>
<li>if (i &lt; 1 || i &gt;= L.length)return false;</li>
<li>e = L.data[i - 1];</li>
<li><p>for (int i = 0; i &lt; L.length; i++)</p>
<ul>
<li>L.data[i - 1] = L.data[i];</li>
</ul>
</li>
<li><p>L.length—;</p>
</li>
<li>return true;</li>
</ul>
</li>
<li><p>}</p>
</li>
<li><ul>
<li></li>
</ul>
</li>
<li><ul>
<li>单链表的定义</li>
</ul>
</li>
<li><ul>
<li>线性表的链式存储</li>
</ul>
</li>
<li><ul>
<li>struct Lnode</li>
</ul>
</li>
<li>{</li>
<li>int data;</li>
<li>Lnode*next;</li>
<li>};</li>
<li><ul>
<li>不能随机存储</li>
</ul>
</li>
<li><ul>
<li>头指针 头节点</li>
</ul>
</li>
<li><ul>
<li>单链表的操作</li>
</ul>
</li>
<li><ul>
<li>GetElem(l,i)</li>
</ul>
</li>
<li><ul>
<li>按位查找</li>
</ul>
</li>
<li><ul>
<li>时间复杂度O(N)</li>
</ul>
</li>
<li><ul>
<li>ListInser(&amp;L,i,e)</li>
</ul>
</li>
<li><ul>
<li>前插</li>
</ul>
</li>
<li><ul>
<li>时间复杂度：O(1) O(n)</li>
</ul>
</li>
<li><ul>
<li>step1</li>
</ul>
</li>
<li><ul>
<li>S-&gt;next=P-&gt;next</li>
</ul>
</li>
<li><ul>
<li>step2</li>
</ul>
</li>
<li><ul>
<li>P-&gt;next=S</li>
</ul>
</li>
<li><ul>
<li>listDelete(&amp;L,i,&amp;e)</li>
</ul>
</li>
<li><ul>
<li>P-&gt;next=P-&gt;next-&gt;next</li>
</ul>
</li>
<li><ul>
<li>判空操作</li>
</ul>
</li>
<li><ul>
<li>常见的单链表</li>
</ul>
</li>
<li><ul>
<li>双链表</li>
</ul>
</li>
<li><ul>
<li>循环链表</li>
</ul>
</li>
<li><ul>
<li>静态链表</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>子主题 3</li>
</ul>
</li>
<li><ul>
<li>线性表的应用</li>
</ul>
</li>
<li><ul>
<li>子主题 4</li>
</ul>
</li>
<li><ul>
<li>顺序表初始化</li>
</ul>
</li>
<li><ul>
<li>sqlist initlist_sq(sqlist L)L.elem=(elemtype*)malloc(sizeof(elemtype));</li>
</ul>
</li>
<li>Int counter;</li>
<li>For(coutnter=0;counter&lt;List_INIT_SIZE;counter++)</li>
<li>Scanf(“%d”,&amp;L.elem[counter]);</li>
<li>L.lenth= List_INIT_SIZE;</li>
<li>L.listsize= List_INIT_SIZE;</li>
<li>Return :l</li>
<li>}</li>
</ul>
</li>
<li><p>1.1线性表的类型定义</p>
<ul>
<li>线性表是具有相同数据类型的n个数据元素的有限序列。n为表长，当n = 0时，为空表。 线性表公式表示：L=（a1,a2,a3…….an）, a1为表头元素，an为表尾元素。除了第一个元素，每个元素都有且仅有一个直接前驱，除了最后一个元素，每个元素有且仅有一个直接后继。 </li>
<li><p>线性表的特征</p>
<ul>
<li><p>有穷性</p>
<ul>
<li>由有限个元素组成，元素个数n：长度</li>
</ul>
</li>
<li><p>有序性</p>
<ul>
<li>线性表元素之间存在序偶关系</li>
</ul>
</li>
<li><p>同一性</p>
<ul>
<li>线性表属于同类数据元素组成，每一个对象都属于同一数据类型</li>
</ul>
</li>
</ul>
</li>
<li><p>线性表抽象数据类型定义</p>
<ul>
<li><p>ADT List</p>
<ul>
<li>数据对象：D={ai|ai∈ElemSet,i=1,2,3,……,n,n≥0)}</li>
<li>数据关系：R={<ai-1,ai>|ai-1,ai∈D}</li>
<li><p>基本操作：</p>
<ul>
<li>initlist(sqlist L)</li>
<li><p>LocateElem(L,e)</p>
<ul>
<li>按值查找</li>
</ul>
</li>
<li><p>GetElem(l,i)</p>
<ul>
<li><p>按位查找</p>
<ul>
<li>时间复杂度O(1)</li>
</ul>
</li>
</ul>
</li>
<li><p>ListInser(&amp;L,i,e)</p>
<ul>
<li><p>前插</p>
<ul>
<li>bool ListInsert(LinkList&amp;L, int i, int e)//插入</li>
</ul>
</li>
</ul>
</li>
<li><p>listDelete(&amp;L,i,&amp;e)</p>
</li>
<li>InitList(&amp;L)</li>
<li>DestroyList(&amp;L)</li>
<li><p>LocateElem(L,e)</p>
<ul>
<li>按值查找</li>
</ul>
</li>
<li><p>GetElem(l,i)</p>
<ul>
<li>按位查找</li>
</ul>
</li>
<li><p>ListInser(&amp;L,i,e)</p>
<ul>
<li><p>前插</p>
<ul>
<li>bool ListInsert(LinkList&amp;L, int i, int e)//插入<br>{<br>if (i<1 || i>L.length + 1)<br>return false;<br>if (i &gt;= 10)<br>return false;<br>for (auto j = L.length; j &gt;= i; j++)<br>L.data[j] = L.data[j - 1];<br>L.data[i - 1] = e;<br>L.length++;<br>return true;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>                        - 时间复杂度：O(1) O(n)

            - listDelete(&amp;L,i,&amp;e)

                - bool ListDelete(LinkList&amp;L, int i, int&amp;e)//删除第i位元素
</code></pre><p>{<br>    if (i &lt; 1 || i &gt;= L.length)return false;<br>    e = L.data[i - 1];</p>
<pre><code>for (int i = 0; i &lt; L.length; i++)
    L.data[i - 1] = L.data[i];
L.length--;
return true;
</code></pre><p>}</p>
<pre><code>            - PrintList(L)
            - Empty（L）
            - Length(L)
</code></pre><h3 id="2-线性表的顺序表示和实现"><a href="#2-线性表的顺序表示和实现" class="headerlink" title="2.线性表的顺序表示和实现"></a>2.线性表的顺序表示和实现</h3><ul>
<li><p>存储结构</p>
<ul>
<li><h1 id="define-LIST-INT-SIZE-100"><a href="#define-LIST-INT-SIZE-100" class="headerlink" title="define LIST_INT_SIZE 100"></a>define LIST_INT_SIZE 100</h1><h1 id="define-LISTINCREAMENT-10"><a href="#define-LISTINCREAMENT-10" class="headerlink" title="define LISTINCREAMENT 10"></a>define LISTINCREAMENT 10</h1>typedef struct<br>{<br>ElemType* elem;//线性表分配的数组空间<br>int length;//线性表长度<br>int listsize;//当前分配的存储容量<br>}SeqList;</li>
</ul>
</li>
<li><p>顺序表初始化</p>
<ul>
<li><p>算法思想</p>
<ul>
<li>构造一个空表，设置一个表的起止位置，表长和可用空间</li>
</ul>
</li>
<li><p>操作实现</p>
<ul>
<li>sqlist initlist_sq(sqlist L)L.elem=(elemtype*)malloc(sizeof(elemtype));<br>Int counter;<br>For(coutnter=0;counter&lt;List_INIT_SIZE;counter++)<br>Scanf(“%d”,&amp;L.elem[counter]);<br>L.lenth= List_INIT_SIZE;<br>L.listsize= List_INIT_SIZE;<br>Return :l<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>顺序表插入</p>
<ul>
<li><p>算法基本思想</p>
<ul>
<li>检查i值是否超出所允许的范围（1≤i≤n+1），若超出，则进行超出范围错误处理</li>
<li>将线性表的第i个元素和她后面的所有元素均向后移动一个位置</li>
<li>将新元素写入到空出的第i个位置上</li>
<li>使线性表的长度+1</li>
</ul>
</li>
<li><p>前插</p>
<ul>
<li>bool ListInsert(LinkList&amp;L, int i, int e)//插入<br>{<br>if (i<1 || i>L.length + 1)<br>return false;<br>if (i &gt;= 10)<br>return false;<br>for (auto j = L.length; j &gt;= i; j++)<br>L.data[j] = L.data[j - 1];<br>L.data[i - 1] = e;<br>L.length++;<br>return true;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>        - 时间复杂度：O(1) O(n)

- 平均移动次数

    - AMN=
</code></pre><ul>
<li><p>顺序表删除</p>
<ul>
<li><p>算法基本思想</p>
<ul>
<li>检查i值是否超出所允许的范围，若超出，则进行超出范围错误处理</li>
<li>将线性表的第i个元素后面的所有元素均镶嵌移动一个位置</li>
<li>使线性表长度减一</li>
</ul>
</li>
<li><p>listDelete(&amp;L,i,&amp;e)</p>
<ul>
<li>bool ListDelete(LinkList&amp;L, int i, int&amp;e)//删除第i位元素<br>{<br>if (i &lt; 1 || i &gt;= L.length)return false;<br>e = L.data[i - 1];</li>
</ul>
<p>for (int i = 0; i &lt; L.length; i++)<br>  L.data[i - 1] = L.data[i];<br>L.length—;<br>return true;<br>}</p>
</li>
</ul>
</li>
</ul>
<pre><code>- 平均移动次数

    - AMN=(n-1)/2

- 顺序存储结构

    - 优点

        - 1：逻辑相邻，物理相邻
        - 2：元素可以随机读取
        - 3：存储空间紧凑

    - 缺点

        - 插入、删除操作需要移动大量的元素
        - 预先分配空间需要按照最大的空间分配，利用不充分
        - 表容量难以扩充
</code></pre><ul>
<li><p>线性表合并问题</p>
<ul>
<li><p>问题描述：假设利用两个线性表La和Lb分别表示两个集合A和B,现要求一个新的集合 A=A∪B。</p>
<ul>
<li>La=(7, 5, 3, 11)</li>
<li>Lb=(2, 6, 3)</li>
<li>La=(7, 5, 3, 11, 2, 6)</li>
</ul>
</li>
<li><p>算法步骤：</p>
<ul>
<li>依次取出Lb中的每个元素，执行以下操作：</li>
<li>在La中查找该元素</li>
<li>如果找不到，则将其插入La的最后</li>
</ul>
</li>
<li><p>2.顺序表实现</p>
<ul>
<li>//合并<br>void Combine(SqList &amp;A, SqList &amp;B)<br>{<br>for (int i = 0; i &lt; B.length; i++)<br>{<br>int count = 0;<br>for (int j = 0; j &lt; A.length; j++)<br>{<br>  if (A.elem[j] == B.elem[i])<br>  {<pre><code>  count += 1;
</code></pre>  }<br>}<br>if (count == 0)<br>{<br>  A.elem[A.length++] = B.elem[i];<br>}<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>数组实现顺序表</p>
<ul>
<li><p>数组静态分配</p>
<ul>
<li><p>struct LinkList<br>{<br>int data[10000];//顺序表中的元素<br>int length;//当前长度<br>};</p>
<ul>
<li></li>
</ul>
</li>
</ul>
</li>
<li><p>数组动态分配</p>
<ul>
<li><p>struct LinkList<br>{<br>int *data;//顺序表中的元素<br>int length;//当前长度<br>};</p>
<ul>
<li>L.data = (int<em>)malloc(sizeof(int)</em>InitSize);</li>
<li>L.data = new int[InitSize];</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-线性表的链式表示和实现"><a href="#3-线性表的链式表示和实现" class="headerlink" title="3.线性表的链式表示和实现"></a>3.线性表的链式表示和实现</h3><ul>
<li><p>特点</p>
<ul>
<li>用一组任意的存储单元存储线性表的数据元素</li>
<li>利用指阵是先用不相邻的存储单元存放逻辑上相邻的元素</li>
<li>每个数据元素a 除存储本身信息外，还需要存储其直接后继的信息</li>
<li><p>节点 数据元素a的存储映像</p>
<ul>
<li><p>数据域</p>
<ul>
<li>元素本身信息</li>
</ul>
</li>
<li><p>指针域</p>
<ul>
<li>指示直接后继的存储位置</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>单链表</p>
<ul>
<li>定义：节点中只含有一个指针域的链表</li>
<li><p>特征：</p>
<ul>
<li>每个元素由节点构成</li>
<li>线性结构</li>
<li>节点可以不连续存储</li>
<li>表可以扩充</li>
</ul>
</li>
<li><p>单链表存储结构的实现</p>
<ul>
<li>typedef struct<br>{<br>ElemType<em> elem;//线性表分配的数组空间<br>struct LNode</em> next;<br>}LNode,*LinkList;</li>
</ul>
</li>
<li><p>链表的优点</p>
<ul>
<li>1：适合随机的插入和删除操作</li>
<li>2：存储空间大小不需要提前设定</li>
<li>3：可以进行动态存储</li>
</ul>
</li>
<li><p>单链表的操作</p>
<ul>
<li><p>GetElem(l,i)</p>
<ul>
<li><p>按位查找</p>
<ul>
<li>时间复杂度O(N)</li>
</ul>
</li>
</ul>
</li>
<li><p>ListInser(&amp;L,i,e)</p>
<ul>
<li><p>前插</p>
<ul>
<li>时间复杂度：O(1) O(n)</li>
<li><p>step1</p>
<ul>
<li>S-&gt;next=P-&gt;next</li>
</ul>
</li>
<li><p>step2</p>
<ul>
<li>P-&gt;next=S</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>listDelete(&amp;L,i,&amp;e)</p>
<ul>
<li>P-&gt;next=P-&gt;next-&gt;next</li>
</ul>
</li>
</ul>
</li>
<li><p>顺序表和链表的比较：</p>
<ul>
<li>1：存取，链表只能从表头开始顺序存取元素；顺序表可以随机存取</li>
<li>2：存储方式，顺序表相邻存储；链表物理存储位置不一定相邻，其逻辑关系是通过指针来链接的</li>
<li>3：顺序表在静态分配时，不可改变内存大小，可能会造成溢出，动态分配时，插入和删除需要移动大量的元素，效率很低。但链表只在需要的时候申请内存，操作灵活</li>
</ul>
</li>
<li><p>链表</p>
<ul>
<li><p>单链表</p>
<ul>
<li><p>//Ha Hb是两个带头结点的头指针， 表示集合A，B 两个链表递增有序排列</p>
<ul>
<li>void Join(LinkList Ha, LinkList Hb, LinkList Hc)<br>{<br>hc = new LinkList;//为Hc 链表创建头节点<br>pc = Hc;<br>pa = Ha-&gt;next;<br>pb = Hb-&gt;next;<br>while ((pa != NULL) &amp;&amp; (pb != BULL)){//扫描单链表Ha，Hb<br>if (pa-&gt;data &lt; pb-&gt;data)<br>pa = pa-&gt;next;<br>else if (pa-&gt;data &gt; pb-&gt;data)<br>pb = pb-&gt;next;<br>else //两链表当前结点值相等<br>//在Hc表尾增加一个新节点<br>{<br>pc-&gt;next = new LinkList;<br>pc = pc-&gt;next;<br>pc-&gt;data = pa-&gt;data;<br>pa = pa-&gt;next;<br>pb = pb-&gt;next;<br>}<br>}<br>pc-&gt;next = NULL;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>    - 双向链表

        - 双链表

            - 单链表结点中只有一个指向其后继的指针，这使得单链表只能从头到尾依次顺序的向后遍历，若要访问某个结点的前驱，只能从头开始遍历，访问后继结点的时间复杂度为O(1)，访问前驱结点的时间复杂度为O(n)；为克服以上缺点，引入双链表，一个结点含有两个指针，分别指向其前驱结点和后继结点。

        - 双向链表的插入顺序

            - 先搞定插入节点的前驱和后继，在搞定其后结点的前驱，最后搞定其前结点的后继

        - 双向链表的删除顺序

            - 要删除双链表的一个结点，无非就是把要删除的结点去掉，然后重新指定前一个结点的前驱节点和后继结点，还有后面那个节点的前驱节点和后继结点。（就是修改p结点前驱结点的next指针和p结点后继结点的prior指针。）原来要删除结点的前驱节点变成原来删除结点的后继节点的前驱节点（p-&gt;next-&gt;prior = p-&gt;piror）,还有就是把原来要删除结点的后继节点变成原来删除结点的前驱节点的后继节点（p-&gt;piror-next = p-&gt;next），
</code></pre><ul>
<li><p>静态链表</p>
<ul>
<li><p>定义</p>
<ul>
<li>数组描述的链表</li>
</ul>
</li>
<li><p>存储结构</p>
<ul>
<li>typedef struct<br>{<br>ElemType<em> elem;//线性表分配的数组空间<br>struct LNode</em> next;<br>}LNode,LinkList[];</li>
</ul>
</li>
<li><p>静态链表初始化</p>
</li>
</ul>
</li>
<li><p>循环链表</p>
<ul>
<li>单链表的变形</li>
<li>知道某个节点地址，可以搜寻所有其他节点</li>
</ul>
</li>
</ul>
<h3 id="4-一元多项式的表示"><a href="#4-一元多项式的表示" class="headerlink" title="4.一元多项式的表示"></a>4.一元多项式的表示</h3><ul>
<li>一元多项式表示</li>
</ul>
<h3 id="线性表按照存储方式可分为顺序表和链表。"><a href="#线性表按照存储方式可分为顺序表和链表。" class="headerlink" title="线性表按照存储方式可分为顺序表和链表。"></a>线性表按照存储方式可分为顺序表和链表。</h3><ul>
<li><p>顺序表</p>
<ul>
<li><p>优点</p>
<ul>
<li>通过下标就可访问元素，因此存取效率高。</li>
</ul>
</li>
<li><p>缺点</p>
<ul>
<li>需预分配空间，分配多了会造成浪费，分配少了会造成“溢出”，因此空间利用率低</li>
<li>插入和删除元素需移动元素，因此插入删除慢。</li>
</ul>
</li>
<li><p>时间复杂度</p>
<ul>
<li>访问元素是O（1）</li>
<li>插入删除元素是O（n）</li>
</ul>
</li>
</ul>
</li>
<li><p>链表</p>
<ul>
<li>相邻数据元素的地址可能不相邻，每个数据元素所占存储空间分成两部分，一部分存放元素值，一部分存放元素之间的关系。</li>
<li><p>优点</p>
<ul>
<li>存储空间是动态分配的，因此没有空间限制；插入和删除元素只需要改变指针指向，因此插入删除快。</li>
</ul>
</li>
<li><p>缺点</p>
<ul>
<li>访问元素需要从开始元素一个一个去查找访问，因此存取效率低。</li>
</ul>
</li>
<li><p>时间复杂度</p>
<ul>
<li>访问元素是O（n）</li>
<li>插入元素是O（1）</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><ul>
<li><p>为什么说顺序存储结构是随机存取的？</p>
<ul>
<li>答：因为顺序存储结构存储的数据是一个挨着一个，是相邻的，也就是说访问任何一个元素的时间是相同的，因为指定了位置，比如说我要取第3个数据，我直接取序号2的的地方拿，不用说又要从0,1，到2这样就行了，所以时间复杂度是O(1)，所以说是随机存取</li>
</ul>
</li>
<li><p>一、线性表的两种存储结构各有哪些优缺点？</p>
<ul>
<li>答：线性表的两种存储结构分别是：顺序存储结构和链式存储结构。顺序存储结构的优点：可以直接存取数据元素，方便灵活，效率高，但插入，和删除需要移动大量的数据元素。因而减低效率；而链式存储结构中采用动态分配，利用率较高，但需增设指示节点之间关系的指针域，存取数据元素不如顺序存储方便，但节点的插入，删除较简单。</li>
</ul>
</li>
<li><p>对于线性表的两种存储结构，若线性表的总数基本稳定，且很少进行插入和删除操作，但要求以最快的速度存取线性表中的元素应选用那种存储结构？是说明理由？</p>
<ul>
<li>答：应选用顺序存储结构，因为每个数据元素的存储位置和线性表的起始位置相差一个和数据元素在线性表中的序号成正比的常数。因此，只要确定了其起始位置，线性表中的任一个数据元素都可随机存取，因此，线性表的顺序存储结构是一种随机存取的存储结构，而链表则是种顺序存取的存储结构。</li>
</ul>
</li>
<li><p>1、设顺序表有19个元素，第一个元素的地址为200，且每个元素占3个字节，则第14个元素的存储地址为（239）</p>
<ul>
<li>解释：一般会有个疑问就是第一个地址200，每个元素3个字节，那13个就是239，第14个是从240开始算还是，142呢？</li>
</ul>
</li>
</ul>
<h2 id="三：栈和队列"><a href="#三：栈和队列" class="headerlink" title="三：栈和队列"></a>三：栈和队列</h2><h3 id="本章目的"><a href="#本章目的" class="headerlink" title="本章目的"></a>本章目的</h3><ul>
<li>目的：介绍栈和队列的逻辑结构定义及在两种存储结构上如何实现栈和队列的基本运算</li>
<li><h3 id="第二章-栈与队列"><a href="#第二章-栈与队列" class="headerlink" title="第二章  栈与队列"></a>第二章  栈与队列</h3></li>
<li><ul>
<li>操作受限</li>
</ul>
</li>
<li><ul>
<li>栈</li>
</ul>
</li>
<li><ul>
<li>类型</li>
</ul>
</li>
<li><ul>
<li>顺序栈</li>
</ul>
</li>
<li><ul>
<li>链栈</li>
</ul>
</li>
<li><ul>
<li>优点：多者栈共享存储空间，提高效率</li>
</ul>
</li>
<li><ul>
<li>便于插入与删除</li>
</ul>
</li>
<li><ul>
<li>共享栈</li>
</ul>
</li>
<li><ul>
<li>让两个顺序栈共享数据空间</li>
</ul>
</li>
<li><ul>
<li>更有效的利用存储空间</li>
</ul>
</li>
<li><ul>
<li>定义</li>
</ul>
</li>
<li><ul>
<li>只允许在一端进行插入或者删除的线性表</li>
</ul>
</li>
<li><ul>
<li>Typedef struct</li>
</ul>
</li>
<li>{</li>
<li>ElemType* base;</li>
<li>ElemType* top;</li>
<li>Int stacksize</li>
<li><p>}</p>
<ul>
<li><ul>
<li>栈顶</li>
</ul>
</li>
<li><ul>
<li>栈底</li>
</ul>
</li>
<li><ul>
<li>空栈</li>
</ul>
</li>
<li></li>
<li><ul>
<li>特性</li>
</ul>
</li>
<li></li>
<li><ul>
<li>后进先出</li>
</ul>
</li>
<li></li>
<li><ul>
<li>栈的操作</li>
</ul>
</li>
<li></li>
<li><ul>
<li>InitStack</li>
</ul>
</li>
<li></li>
<li><ul>
<li>：S.top=S.base</li>
</ul>
</li>
<li></li>
<li><ul>
<li>StackEmpty</li>
</ul>
</li>
<li></li>
<li><ul>
<li>S.top==S.base</li>
</ul>
</li>
<li></li>
<li><ul>
<li>Push</li>
</ul>
</li>
<li><ul>
<li>Pop</li>
</ul>
</li>
<li><ul>
<li>GetTop</li>
</ul>
</li>
<li><ul>
<li>ClearStack</li>
</ul>
</li>
<li></li>
<li><ul>
<li>栈的实现</li>
</ul>
</li>
<li></li>
<li><ul>
<li>队列</li>
</ul>
</li>
<li></li>
<li><ul>
<li>循环队列</li>
</ul>
</li>
<li></li>
<li><ul>
<li>插入元素</li>
</ul>
</li>
<li></li>
<li><ul>
<li>队尾指针+1</li>
</ul>
</li>
<li></li>
<li><ul>
<li>删除元素</li>
</ul>
</li>
<li></li>
<li><ul>
<li>队头指针+1</li>
</ul>
</li>
<li></li>
<li><ul>
<li>链式队列</li>
</ul>
</li>
<li><ul>
<li>双端队列</li>
</ul>
</li>
<li><ul>
<li>队列长度的计算</li>
</ul>
</li>
<li><ul>
<li>头/尾出现指向下一个节点的情况</li>
</ul>
</li>
<li></li>
<li><ul>
<li>(rear-front+maxsize)%maxsize</li>
</ul>
</li>
<li></li>
<li><ul>
<li>栈与队列的应用</li>
</ul>
</li>
<li></li>
<li><ul>
<li>栈在符号匹配的应用</li>
</ul>
</li>
<li><ul>
<li>再在表达式求值</li>
</ul>
</li>
<li><ul>
<li>递归</li>
</ul>
</li>
<li><ul>
<li>队列在层次遍历的应用</li>
</ul>
</li>
<li><ul>
<li>队列在计算机系统</li>
</ul>
</li>
<li></li>
<li><ul>
<li>子主题 7</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>推广</li>
</ul>
</li>
<li><ul>
<li>一维数组</li>
</ul>
</li>
<li><ul>
<li>多维数组</li>
</ul>
</li>
<li><ul>
<li>压缩存储</li>
</ul>
</li>
<li><ul>
<li>稀疏矩阵</li>
</ul>
</li>
<li><ul>
<li>栈队列线性表，都是线性结构，仅仅是运算不同</li>
</ul>
</li>
<li><ul>
<li>栈与队列的区别</li>
</ul>
</li>
<li><ul>
<li>都是线性表</li>
</ul>
</li>
<li><ul>
<li>存储结构可能顺序可能链序</li>
</ul>
</li>
<li><ul>
<li>插入、删除操作的限定不同</li>
</ul>
</li>
<li><ul>
<li>考试中的实现技巧</li>
</ul>
</li>
<li><ul>
<li>声明栈并初始化</li>
</ul>
</li>
<li><ul>
<li>Elemtype stack[maxSize];int top=1;</li>
</ul>
</li>
<li><ul>
<li>元素进栈</li>
</ul>
</li>
<li><ul>
<li>stack[++top]=x;</li>
</ul>
</li>
<li><ul>
<li>元素退栈</li>
</ul>
</li>
<li><ul>
<li>x=stack[top—];</li>
</ul>
</li>
</ul>
<h3 id="3-1-栈"><a href="#3-1-栈" class="headerlink" title="3.1 栈"></a>3.1 栈</h3><ul>
<li><p>3.1.1 抽象数据类型</p>
<ul>
<li>栈( stack )是限定仅在表尾进行捕入和删除操作的线性表。</li>
<li>我们把允许插入和删除的一端称为栈顶 （top），另一端称为栈底 (bottom)，不含任何数据元素的栈称为空栈。栈又称为后进先出 (Last In Filrst Out) 的线性表，简称 LlFO 结构 。</li>
<li>首先它是一个线性表，也就是说，栈元素具有线性关系，即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作，这里表尾是指栈顶，而不是栈底。</li>
<li>它的特殊之处就在于限制了这个线性表的插入和删除位置，它始终只在栈顶进行。这也就使得:栈底是固定的，最先进栈的只能在栈底。</li>
<li><p>抽象数据类型定义</p>
<ul>
<li>ADT Stack{</li>
<li>数据对象：D={ai|ai∈ElemSet, i=1,2, …,n, n≥0}</li>
<li>数据关系：R1={<ai-1,ai>|ai-1,ai∈D, i=1,2, …,n }</li>
<li>约定an端为栈顶，a1端为栈底。</li>
<li><p>基本操作</p>
<ul>
<li><p>InitStack( &amp;S )</p>
<ul>
<li>操作结果：构造一个空栈S。</li>
</ul>
</li>
<li><p>DestroyStack ( &amp;S )</p>
<ul>
<li>初始条件：栈S已存在。</li>
<li>操作结果：销毁栈S。</li>
</ul>
</li>
<li><p>ClearStack( &amp;S )</p>
<ul>
<li>初始条件：栈S已存在。</li>
<li>操作结果：将S清为空栈。</li>
</ul>
</li>
<li><p>StackEmpty( S )</p>
<ul>
<li>初始条件：栈S已存在。</li>
<li>操作结果：若S为空栈，则返回TRUE，否则返回FALSE。</li>
</ul>
</li>
<li><p>StackLength( S )</p>
<ul>
<li>初始条件：栈S已存在。</li>
<li>操作结果：返回S的数据元素个数，即栈的长度。</li>
</ul>
</li>
<li><p>GetTop( S, &amp;e )</p>
<ul>
<li>初始条件：栈S已存在且非空。</li>
<li>操作结果：用e返回S的栈顶元素。</li>
</ul>
</li>
<li><p>Push( &amp;S, e )</p>
<ul>
<li>初始条件：栈S已存在。</li>
<li>操作结果：插入元素e为新的栈顶元素。</li>
</ul>
</li>
<li><p>Pop( &amp;S, &amp;e )</p>
<ul>
<li>初始条件：栈S已存在且非空。</li>
<li>操作结果：删除S的栈顶元素，并用e返回其值。</li>
</ul>
</li>
<li><p>StackTraverse( S, visit() )</p>
<ul>
<li>初始条件：栈S已存在且非空。</li>
<li>操作结果：从栈底到栈顶依次对S的每个数据元素调用函数visit()。一旦visit()失败，则操作失败。</li>
</ul>
</li>
</ul>
</li>
<li><p>ADT Stack</p>
<h1 id="include"><a href="#include" class="headerlink" title="include"></a>include<stdio.h></h1><h1 id="include-1"><a href="#include-1" class="headerlink" title="include"></a>include<malloc.h></h1><h1 id="define-STACK-INIT-SIZE-1"><a href="#define-STACK-INIT-SIZE-1" class="headerlink" title="define STACK_INIT_SIZE 1"></a>define STACK_INIT_SIZE 1</h1><h1 id="define-STACKINCREMENT-10"><a href="#define-STACKINCREMENT-10" class="headerlink" title="define STACKINCREMENT 10"></a>define STACKINCREMENT 10</h1><p>typedef char ElemType;<br>struct SqStack<br>{<br>ElemType <em>elem;<br>ElemType   </em>top;<br>int stacksize;<br>};<br>int InitStack(struct SqStack <em>S)<br>{<br>S-&gt;elem=(ElemType </em>)malloc(STACK_INIT_SIZE <em> sizeof(ElemType));<br>if(!S-&gt;elem)<br>{<br>printf(“初始化栈失败”);<br>return 0;<br>}<br>else<br>{<br>S-&gt;top=S-&gt;elem;<br>S-&gt;stacksize= STACK_INIT_SIZE;<br>printf(“初始化栈成功\n”);<br>return 1;<br>}<br>}<br>int Push(struct SqStack </em>S,ElemType x)<br>{<br>if(S-&gt;top-S-&gt;elem&gt;=S-&gt;stacksize)<br>{<br>S-&gt;elem=(ElemType <em>)realloc(S-&gt;elem,(S-&gt;stacksize+STACKINCREMENT) </em> sizeof(ElemType));<br>if(!S-&gt;elem)<br>{     printf(“开辟空间失败\n”);<br>   return 0;<br>}<br>else<br>{<br>  S-&gt;top=S-&gt;elem+S-&gt;stacksize;<br>  S-&gt;stacksize+=STACKINCREMENT;<br>}<br>}<br><em>S-&gt;top=x;<br>S-&gt;top++;<br>return x;<br>}<br>int Pop(struct SqStack </em>S,ElemType x)<br>{<br>if(S-&gt;top==S-&gt;elem)<br>{<br>printf(“栈空\n”);<br>return 0;<br>}<br>else<br>{<br>S-&gt;top—;<br>x=<em>S-&gt;top;<br>return x;<br>}<br>}<br>int GetTop(struct SqStack </em>S,ElemType x)<br>{<br>if(S-&gt;top==S-&gt;elem)<br>{<br>printf(“栈空\n”);<br>7楼</p>
<p>return 0;<br>}<br>else<br>{<br>x=*(S-&gt;top-1);</p>
<p>return x;<br>}<br>}<br>int StackLength(struct SqStack <em>S)<br>{<br>int n;<br>n=S-&gt;top-S-&gt;elem;<br>return(n);<br>}<br>void StackEmpty(struct SqStack </em>S)<br>{<br>if(S-&gt;top==S-&gt;elem)</p>
<p>printf(“栈为空\n”);<br>else<br>printf(“栈不为空\n”);<br>}<br>int VisitStack(struct SqStack <em>S)<br>{<br>int k=0;<br>while(S-&gt;top!=S-&gt;elem)<br>{<br>—S-&gt;top;<br>k++;<br>printf(“%c “,</em>S-&gt;top);<br>}<br>S-&gt;top+=k;<br>return 1;<br>}<br>int ClearStack(struct SqStack *S)<br>{<br>if(S-&gt;top==S-&gt;elem)<br>return 0;<br>else<br>{  S-&gt;top=S-&gt;elem;<br>return 1;<br>}</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>}<br>int DestoryStack(struct SqStack *S)<br>{<br>    free(S-&gt;elem);<br>    S-&gt;elem=NULL;<br>    S-&gt;top=NULL;<br>    S-&gt;stacksize=0;<br>    return 1;<br>}</p>
<p>void main()<br>{    int y;<br>    struct SqStack A;<br>    ElemType x=0;<br>    ElemType e;<br>    int cmd;<br>    printf(“<strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><em>*</em></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>\n”);<br>    printf(“1－初始化栈     2－进栈        3－取栈顶元素      4－求栈长    5－销毁栈\n”);<br>    printf(“6－判空         7－遍历栈      8－出栈            9－清空栈    0-退出\n”);<br>    printf(“<strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><em>*</em></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>\n”);</p>
<p>do{    printf(“enter your choice “);<br>    scanf(“%d”,&amp;cmd);<br>     e=getchar();<br>    switch(cmd)<br>    {<br>case 1:  InitStack(&amp;A);<br>             break;<br>    case 2:   printf(“e=”);<br>             e=getchar();<br>             y=Push(&amp;A,e);printf(“进栈元素为&gt;&gt;%c\n”,y);<br>             break;<br>    case 3:  y=GetTop(&amp;A,x);<br>             if(!y)<br>             printf(“没有栈顶元素&gt;&gt;\n”);<br>             else<br>             printf(“栈顶元素为&gt;&gt;%c\n”,y);break;<br>    case 4:  y=StackLength(&amp;A);<br>             printf(“栈中元素个数为&gt;&gt;%d\n”,y);break;<br>    case 5:  if(DestoryStack(&amp;A));<br>             printf(“栈销毁成功&gt;&gt;\n”);break;<br>    case 6:  StackEmpty(&amp;A);break;<br>    case 7:  printf(“出栈序列为&gt;&gt;”);<br>             VisitStack(&amp;A);<br>             printf(“\n”);<br>             break;<br>    case 8:  y=Pop(&amp;A,x);<br>             if(!y)<br>             printf(“没有栈顶元素可出&gt;&gt;\n”);<br>             else<br>             printf(“出栈元素为&gt;&gt;%c\n”,y);<br>              break;<br>    case 9:  y=ClearStack(&amp;A);<br>             if(!y)<br>                 printf(“栈本身为空&gt;&gt;\n”);<br>             else<br>                 printf(“栈成功清空&gt;&gt;\n”);<br>             break;<br>    default: break;<br>    }<br>}while(cmd!=0);<br>}</p>
<ul>
<li><p>3.1.2 栈的表示和实现</p>
<ul>
<li><p>顺序栈定义</p>
<ul>
<li>typedef struct<br>{<br>int<em> base;    //栈底指针<br>int</em> top;    //栈顶指针<br>int stacksize;    //栈可用的最大容量<br>}SqStack;</li>
<li><p>顺序栈的初始化</p>
<ul>
<li>//顺序栈的初始化<br>bool InitStack(SqStack&amp; S)<br>{<br>S.base = new int[MAXSIZE];    //分配空间<br>if (!S.base) return 0;        //存储分配失败<br>S.top = S.base;                //栈顶指针等于栈底指针，为空栈<br>S.stacksize = MAXSIZE;        //栈最大容量为MAXSIZA<br>return 0;<br>}</li>
</ul>
</li>
<li><p>顺序栈入栈</p>
<ul>
<li><em>S.top++ = e;拆分成</em>S.top = e;与S.top++;</li>
<li>//顺序栈入栈<br>bool Push(SqStack&amp; S, int e)<br>{<br>if (S.top - S.base == MAXSIZE) return 0;    //栈满<br>*S.top++ = e;<br>return 1;<br>}</li>
</ul>
</li>
<li><p>顺序栈出栈</p>
<ul>
<li>//顺序栈出栈<br>bool Pop(SqStack&amp; S, int &amp;e)<br>{<br>if (S.top == S.base) return 0;    //栈空<br>e = —*S.top;<br>return 1;<br>}</li>
</ul>
</li>
<li><p>取栈顶元素</p>
<ul>
<li>int GetTop(SqStack&amp; S)<br>{<br>if (S.top != S.base) return *(S.top - 1);        //栈非空<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>链栈</p>
<ul>
<li><p>定义</p>
<ul>
<li>typedef struct StackNode<br>{<br>int data;<br>struct StackNode<em> next;<br>}StackNode, </em>LinkStack;</li>
</ul>
</li>
<li><p>链栈的初始化</p>
<ul>
<li>bool InitStack(LinkStack&amp; S)<br>{<br>S == NULL;<br>return 1;<br>}</li>
</ul>
</li>
<li><p>链栈的入栈</p>
<ul>
<li>bool Push(LinkStack&amp; S, int e)<br>{<br>LinkStack p = new StackNode;    //新增栈顶的节点<br>p-&gt;data = e;<br>p-&gt;next = S;        //使S能找到下一节点的地址，便于出栈操作<br>S = p;                //S指向栈顶<br>}</li>
</ul>
</li>
<li><p>链表的出栈</p>
<ul>
<li>bool Pop(LinkStack&amp; S, int&amp; e)<br>{<br>if (S == NULL) return 0;    //栈非空<br>e = S-&gt;data;<br>LinkStack p = S;            //p保存栈顶元素空间，以便释放<br>S = S-&gt;next;<br>delete p;<br>return 1;<br>}</li>
</ul>
</li>
<li><p>取栈顶元素</p>
<ul>
<li>int GetTop(LinkStack S)<br>{<br>return S-&gt;data;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-2-栈的应用举例"><a href="#3-2-栈的应用举例" class="headerlink" title="3.2 栈的应用举例"></a>3.2 栈的应用举例</h3><ul>
<li><p>数值转换</p>
<ul>
<li>void conversion()<br>{<br>InitStack(S);<br>scanf(“%d”, N);<br>while (N) {<br>  Push(S, N % 8);<br>  N = N / 8;<br>}<br>while (!StackEmpty(S))<br>{<br>  Pop(S, e);<br>  printf(“%d”, e);<br>}<br>}</li>
</ul>
</li>
<li><p>括号匹配的检验</p>
</li>
<li>行编辑程序问题</li>
<li>迷宫求解</li>
<li>表达式求值</li>
</ul>
<h3 id="3-3-栈与递归"><a href="#3-3-栈与递归" class="headerlink" title="3.3 栈与递归"></a>3.3 栈与递归</h3><h3 id="3-4-队列"><a href="#3-4-队列" class="headerlink" title="3.4 队列"></a>3.4 队列</h3><h3 id="3-5-离散模拟"><a href="#3-5-离散模拟" class="headerlink" title="3.5 离散模拟"></a>3.5 离散模拟</h3><h3 id="问题-1"><a href="#问题-1" class="headerlink" title="问题"></a>问题</h3><ul>
<li><p>问题</p>
<ul>
<li><p>1、设入栈顺序为A,B,C,D,E.则出栈序列不可能为（B）<br>A、EDCBA<br>B、ADEBC<br>C、ABCDE<br>D、ABDCE</p>
<ul>
<li>这种题目都有一种规律:先出来的序号后面一定不能有比他本身小的从小到大排列的序列。<br>比如<br>12345<br>45321 正确<br>43512（5后面有比它本身小且从小到大排序所以是错的）</li>
</ul>
</li>
<li><p>2、若进栈序列为1,2,3.4假定进栈和出栈可以穿插进行，则可能的出栈序列是(D)<br>A、2,4,1,3<br>B、3,1,4,2<br>C、3,4,1,2<br>D、1,2,3,4</p>
<ul>
<li>原则：如果想要后面的先出栈，那么按照1234的入栈顺序，前面的必须已经入栈，比如要让3第一个出栈，那么入栈顺序为：<br>1入栈，2入栈，3入栈，之后3出栈，这样3就是第一个出栈的，如果想让4接着出栈，那么就4入栈，然后再出栈，然后2出栈，1出栈<br>最后出栈顺序为：<br>3421<br>以此规则分别分析ABCD</li>
</ul>
</li>
</ul>
</li>
<li><p>栈的应用</p>
<ul>
<li><p>循环队列（front:队头，rear:队尾，Maxsize:队列长度）</p>
<ul>
<li><p>往循环队列删除元素</p>
<ul>
<li>R = (R+1)%M</li>
</ul>
</li>
<li><p>往循环队列插入元素</p>
<ul>
<li>F= (F+1)%M</li>
</ul>
</li>
<li><p>判断循环队列满</p>
<ul>
<li>R+1%M = F</li>
</ul>
</li>
<li><p>判断循环队列空</p>
<ul>
<li>R = F</li>
</ul>
</li>
<li><p>判断循环队列元素个数</p>
<ul>
<li>(R-F+M)％M</li>
</ul>
</li>
</ul>
</li>
<li><p>前缀，中缀和后缀表达式</p>
</li>
<li><p>中缀表达式转后缀表达式：</p>
<ul>
<li>从左到右遍历中缀表达式的每个数字和运算符，是数字就直接输出，如果是运算符的话，判断当前要进栈的运算符跟栈顶的运算符比较优先级，如果栈顶运算符优先级低于当前要进栈的运算符，就不输出，直接进栈，如果栈顶运算符优先级高于当前要进栈的运算符，就输出栈顶运算符，一直遍历到表达式最后。</li>
</ul>
</li>
<li><p>中缀表达式转前缀表达式：</p>
<ul>
<li>从右向左遍历中缀表达式的每个数字和运算符，是数字就直接输出，如果是运算符的话，判断当前要进栈的运算符跟栈顶的运算符比较优先级，如果栈顶运算符优先级低于当前要进栈的运算符，就不输出，直接进栈，如果栈顶运算符优先级高于当前要进栈的运算符，就输出栈顶运算符一直遍历到表达式最后，如果同级就入栈。</li>
</ul>
</li>
<li><p>后缀表达式转中缀表达式</p>
</li>
<li>前缀表达式转中缀表达式</li>
</ul>
</li>
</ul>
<h2 id="四、串"><a href="#四、串" class="headerlink" title="四、串"></a>四、串</h2><h3 id="问题-2"><a href="#问题-2" class="headerlink" title="问题"></a>问题</h3><ul>
<li>1、字符串”qiniu”根据顺序不同有（C）种排列组合的方式？<br>A、96    B、72    C、60    D、24</li>
<li>2、若串S=′software′,其子串的数目是(B)<br>A、8   B、37    C、36    D、9</li>
<li>3、字符串′ababaabab′的nextval为(A)<br>A、(0,1,0,1,0,4,1,0,1)<br>B、(0,1,0,1,0,2,1,0,1)<br>C、(0,1,0,1,0,0,0,1,1)<br>D、(0,1,0,1,0,1,0,1,1)</li>
<li><h3 id="第四章-树"><a href="#第四章-树" class="headerlink" title="第四章  树"></a>第四章  树</h3></li>
<li><ul>
<li>树</li>
</ul>
</li>
<li><ul>
<li>概念</li>
</ul>
</li>
<li><ul>
<li>定义</li>
</ul>
</li>
<li><ul>
<li>根节点</li>
</ul>
</li>
<li><ul>
<li>子孙节点</li>
</ul>
</li>
<li><ul>
<li>父节点</li>
</ul>
</li>
<li><ul>
<li>子节点</li>
</ul>
</li>
<li><ul>
<li>兄弟节点</li>
</ul>
</li>
<li><ul>
<li>度</li>
</ul>
</li>
<li><ul>
<li>子节点的个数</li>
</ul>
</li>
<li><ul>
<li>树的度是  节点度的最大值</li>
</ul>
</li>
<li><ul>
<li>分支节点与叶子节点</li>
</ul>
</li>
<li><ul>
<li>分支节点</li>
</ul>
</li>
<li><ul>
<li>度&gt;0</li>
</ul>
</li>
<li><ul>
<li>结点的层次、高度、深度</li>
</ul>
</li>
<li><ul>
<li>路径</li>
</ul>
</li>
<li><ul>
<li>树中两个结点之间所经过的结点序列</li>
</ul>
</li>
<li><ul>
<li>自上而下</li>
</ul>
</li>
<li><ul>
<li>路径长度</li>
</ul>
</li>
<li><ul>
<li>路径上所经历边的个数</li>
</ul>
</li>
<li><ul>
<li>树是由n个节点的有限集合</li>
</ul>
</li>
<li><ul>
<li>有且只有一个特定的根</li>
</ul>
</li>
<li><ul>
<li>当n&gt;1时，其余节点可分为m个互不相交的有限集合，其中每个集合是一棵树，称为根结点的子树</li>
</ul>
</li>
<li><ul>
<li>n个节点有n-1条边</li>
</ul>
</li>
<li><ul>
<li>逻辑结构</li>
</ul>
</li>
<li><ul>
<li>存储结构</li>
</ul>
</li>
<li><ul>
<li>双亲表示法</li>
</ul>
</li>
<li><ul>
<li>每个结点都有一个指示器指示双亲结点的位置</li>
</ul>
</li>
<li><ul>
<li>优点</li>
</ul>
</li>
<li><ul>
<li>易找出他的双亲结点</li>
</ul>
</li>
<li><ul>
<li>缺点</li>
</ul>
</li>
<li><ul>
<li>孩子结点，需遍历所有结点</li>
</ul>
</li>
<li><ul>
<li>孩子表示法</li>
</ul>
</li>
<li><ul>
<li>孩子兄弟表示法</li>
</ul>
</li>
<li><ul>
<li>二叉树作为存储结构</li>
</ul>
</li>
<li><ul>
<li>左结点</li>
</ul>
</li>
<li><ul>
<li>第一个孩子结点</li>
</ul>
</li>
<li><ul>
<li>右结点</li>
</ul>
</li>
<li><ul>
<li>下一个兄弟结点</li>
</ul>
</li>
<li><ul>
<li>性质</li>
</ul>
</li>
<li><ul>
<li>树中结点个数=所有结点的度+1</li>
</ul>
</li>
<li><ul>
<li>度为m的树第i曾至多有m^(i-1)个结点</li>
</ul>
</li>
<li><ul>
<li>具有n个结点的m叉树的最小高度是logm(n(m-1)+1)(向上取整)</li>
</ul>
</li>
<li><ul>
<li>操作</li>
</ul>
</li>
<li><ul>
<li>遍历</li>
</ul>
</li>
<li><ul>
<li>树的先根遍历</li>
</ul>
</li>
<li><ul>
<li>树非空，则先访问根节点，在从左到右顺序遍历根节点的每一个子树</li>
</ul>
</li>
<li><ul>
<li>树的后根遍历</li>
</ul>
</li>
<li><ul>
<li>树非空，则按从左到右顺序遍历根节点的每一个子树，之后访问根节点</li>
</ul>
</li>
<li><ul>
<li>先序遍历森林</li>
</ul>
</li>
<li><ul>
<li>若森林非空，访问森林的第一棵树的根节点，之后遍历第一棵树中根节点的子树森林，最后，先序遍历除去第一棵树之后剩余的树构成的森林</li>
</ul>
</li>
<li><ul>
<li>中序遍历森林</li>
</ul>
</li>
<li><ul>
<li>若森林非空，中序遍历一棵树中根节点的子树森林，之后访问森林的一棵树的根节点，最后，中序遍历除去第一棵树之后剩余的树构成的森林</li>
</ul>
</li>
<li><ul>
<li>森林的存储</li>
</ul>
</li>
<li><ul>
<li>森林与二叉树的转化</li>
</ul>
</li>
<li><ul>
<li>线索二叉树</li>
</ul>
</li>
<li><ul>
<li>二叉排序树</li>
</ul>
</li>
<li><ul>
<li>并查集</li>
</ul>
</li>
<li><ul>
<li>子主题 4</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>二叉树</li>
</ul>
</li>
<li><ul>
<li>概念</li>
</ul>
</li>
<li><ul>
<li>定义</li>
</ul>
</li>
<li><ul>
<li>n个结点的有序集合，n可以为0</li>
</ul>
</li>
<li><ul>
<li>根节点与两个互不相交的二个子树组成</li>
</ul>
</li>
<li><ul>
<li>左右</li>
</ul>
</li>
<li><ul>
<li>二叉树可以为空</li>
</ul>
</li>
<li><ul>
<li>有序树</li>
</ul>
</li>
<li><ul>
<li>度为2的有序树至少有3个结点</li>
</ul>
</li>
<li><ul>
<li>子结点的次序是相对的</li>
</ul>
</li>
<li><ul>
<li>满二叉树</li>
</ul>
</li>
<li><ul>
<li>一颗高度为h，含有2^h-1结点的二叉树</li>
</ul>
</li>
<li><ul>
<li>i(根节点默认为1)</li>
</ul>
</li>
<li><ul>
<li>2*i</li>
</ul>
</li>
<li><ul>
<li>2*i+1</li>
</ul>
</li>
<li><ul>
<li>完全二叉树</li>
</ul>
</li>
<li><ul>
<li>每个结点与满二叉树编号次序相同</li>
</ul>
</li>
<li><ul>
<li>性质</li>
</ul>
</li>
<li><ul>
<li>i&lt;[n/2]  结点为分支结点，否则 叶子节点</li>
</ul>
</li>
<li><ul>
<li>子主题 2</li>
</ul>
</li>
<li><ul>
<li>特征</li>
</ul>
</li>
<li><ul>
<li>有且只有一个特定的根</li>
</ul>
</li>
<li><ul>
<li>子主题 2</li>
</ul>
</li>
<li><ul>
<li>性质</li>
</ul>
</li>
<li><ul>
<li>非空二叉树的叶子节点树=度为2的结点数+1</li>
</ul>
</li>
<li><ul>
<li>非空二叉树第k层至多有2^(k-1)个结点</li>
</ul>
</li>
<li><ul>
<li>高度为h的二叉树至多有2^h-1ge个结点</li>
</ul>
</li>
<li><ul>
<li>i</li>
</ul>
</li>
<li><ul>
<li>2*i</li>
</ul>
</li>
<li><ul>
<li>2*i+1</li>
</ul>
</li>
<li><ul>
<li>具有n个结点的完全二叉树的高度为log2(n)+1</li>
</ul>
</li>
<li><ul>
<li>结点i所在的层次为log2(i)+1</li>
</ul>
</li>
<li><ul>
<li>存储结构</li>
</ul>
</li>
<li><ul>
<li>顺序存储</li>
</ul>
</li>
<li><ul>
<li>1</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>2</li>
</ul>
</li>
<li><ul>
<li>3</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>4</li>
</ul>
</li>
<li><ul>
<li>5</li>
</ul>
</li>
<li>- </li>
<li><ul>
<li>6</li>
</ul>
</li>
<li><ul>
<li>7</li>
</ul>
</li>
<li>- </li>
<li>- </li>
<li>- </li>
<li><ul>
<li>链式存储</li>
</ul>
</li>
<li><ul>
<li>结点结构【lchild,data,rchild】</li>
</ul>
</li>
<li><ul>
<li>代码</li>
</ul>
</li>
<li><ul>
<li>typedef sturct BitNode</li>
</ul>
</li>
<li>{</li>
<li>ElemType data;</li>
<li>struct BitNode <em>lchild,</em>rchild;</li>
<li>}BitNode,*BiTree;</li>
<li><ul>
<li>二叉树</li>
</ul>
</li>
<li><ul>
<li>逻辑结构</li>
</ul>
</li>
<li><ul>
<li>线索二叉树</li>
</ul>
</li>
<li><ul>
<li>物理结构（链表）</li>
</ul>
</li>
<li><ul>
<li>操作</li>
</ul>
</li>
<li><ul>
<li>先序遍历</li>
</ul>
</li>
<li><ul>
<li>递归算法</li>
</ul>
</li>
<li><ul>
<li>非递归算法</li>
</ul>
</li>
<li><ul>
<li>void PreorderTraverse(Bitree T)</li>
</ul>
</li>
<li>{</li>
<li>InitStack(s);</li>
<li>BiTree p=T;</li>
<li>while (p != NULL || !Emptystack(s))</li>
<li>{</li>
<li>if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子</li>
<li>{</li>
<li>visit(p);</li>
<li>Push(s, p);</li>
<li>p = p-&gt;left;</li>
<li>}</li>
<li>else//当他完成遍历后，去遍历其右孩子</li>
<li>{</li>
<li>Pop(s, p); p = p-&gt;right;</li>
<li>}</li>
<li>}</li>
<li>}</li>
<li><ul>
<li>中序遍历</li>
</ul>
</li>
<li><ul>
<li>最后一个节点</li>
</ul>
</li>
<li><ul>
<li>从根节点沿右子女指针链走到底</li>
</ul>
</li>
<li><ul>
<li>若该点是叶子节点</li>
</ul>
</li>
<li><ul>
<li>前序与中序最易一个节点相同</li>
</ul>
</li>
<li><ul>
<li>不是叶子节点</li>
</ul>
</li>
<li><ul>
<li>前序遍历的最后一个节点在他的左子树</li>
</ul>
</li>
<li><ul>
<li>非递归算法</li>
</ul>
</li>
<li><ul>
<li>void InorderTraverse(Bitree T)</li>
</ul>
</li>
<li>{</li>
<li>InitStack(s);</li>
<li>Push(s, T);</li>
<li>while (!Emptystack(s))</li>
<li>{</li>
<li>while (GetTop(s, p) &amp;&amp; p)//向左走到尽头</li>
<li>Push(s.p-&gt;lchild);</li>
<li>Pop(s, p);</li>
<li>if (!Emptystack(s))//得到一个新节点，访问后压入栈中，之后访问他的左孩子</li>
<li>{</li>
<li>Pop(s, p);</li>
<li>visit(p);</li>
<li>Push(s, p-&gt;rchild);</li>
<li>}</li>
<li>}</li>
<li>}</li>
<li><ul>
<li>void InorderTraverse(Bitree T)</li>
</ul>
</li>
<li>{</li>
<li>InitStack(s);</li>
<li>BiTree p = T;</li>
<li>while (p != NULL || !Emptystack(s))</li>
<li>{</li>
<li>if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子</li>
<li>{</li>
<li>Push(s, p);</li>
<li>p = p-&gt;left;</li>
<li>}</li>
<li>else//当他完成遍历后，去遍历其右孩子</li>
<li>{</li>
<li>Pop(s, p); </li>
<li>visit(p);</li>
<li>p = p-&gt;right;</li>
<li>}</li>
<li>}</li>
<li>}</li>
<li><ul>
<li>后序遍历</li>
</ul>
</li>
<li><ul>
<li>退回时访问根节点</li>
</ul>
</li>
<li><ul>
<li>已知先序遍历与后序遍历</li>
</ul>
</li>
<li><ul>
<li>序列刚好相反</li>
</ul>
</li>
<li><ul>
<li>不可能同时有左右节点</li>
</ul>
</li>
<li><ul>
<li>非递归算法</li>
</ul>
</li>
<li><ul>
<li>void PreorderTraverse(Bitree T)</li>
</ul>
</li>
<li>{</li>
<li>InitStack(s);</li>
<li>BiTree p = T,r=NULL;</li>
<li>while (p != NULL || !Emptystack(s))</li>
<li>{</li>
<li>if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子</li>
<li>{</li>
<li>Push(s, p);</li>
<li>p = p-&gt;left;</li>
<li>}</li>
<li>else//不能直接退栈</li>
<li>{</li>
<li>getTop(s, p);</li>
<li>if (p-&gt;right != NULL&amp;&amp;p-&gt;right != r)p = p-&gt;right;</li>
<li>else</li>
<li>{</li>
<li>Pop(s, p); visit(p); r = p; p = NULL;</li>
<li>}</li>
<li>}</li>
<li>}</li>
<li><p>}</p>
<ul>
<li><ul>
<li>层次遍历</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>队列实现</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>线索二叉树</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>加快遍历速度</li>
</ul>
</li>
</ul>
</li>
<li></li>
<li><ul>
<li>应用</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>排序二叉树</li>
</ul>
</li>
<li><ul>
<li>平衡二叉树</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li><p>树上任意结点的左子树右子树深度之差不超过一</p>
<ul>
<li><ul>
<li>左子树-右子树深度</li>
</ul>
</li>
<li><ul>
<li>节点递推公式</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>0</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>0</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>1</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>1</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>2</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>2</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>h</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>1+(h-1)+(h-2)</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>哈夫曼树</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li><p>只有度为0、2的节点</p>
<ul>
<li><ul>
<li>节点总数</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li><p>n=n0+n2</p>
<ul>
<li><ul>
<li>n0=n2+1</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>度为m的哈夫曼</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li></li>
</ul>
</li>
</ul>
</li>
<li></li>
<li><ul>
<li>常考题目</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>算法：先序中户后序遍历层次遍历</li>
</ul>
</li>
<li><ul>
<li>编写求二叉树的叶子节点的算法</li>
</ul>
</li>
<li><ul>
<li>求二叉树的深度</li>
</ul>
</li>
<li><ul>
<li>由遍历序列恢复二叉树</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>森林</li>
</ul>
</li>
<li><ul>
<li>概念</li>
</ul>
</li>
<li><ul>
<li>定义</li>
</ul>
</li>
<li><ul>
<li>m棵互不相交的树的集合</li>
</ul>
</li>
<li><ul>
<li>树是由n个节点的有限集合</li>
</ul>
</li>
<li><ul>
<li>有且只有一个特定的根</li>
</ul>
</li>
<li><ul>
<li>当n&gt;1时，其余节点可分为m个互不相交的有限集合，其中每个集合是一棵树，称为根结点的子树</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>子主题 1</li>
</ul>
</li>
<li><ul>
<li>n个节点有n-1条边</li>
</ul>
</li>
<li><ul>
<li>存储结构</li>
</ul>
</li>
<li><ul>
<li>g</li>
</ul>
</li>
<li><ul>
<li>逻辑结构</li>
</ul>
</li>
</ul>
<h2 id="第五章-图"><a href="#第五章-图" class="headerlink" title="第五章 图"></a>第五章 图</h2><h3 id="5-1-图的定义"><a href="#5-1-图的定义" class="headerlink" title="5.1 图的定义"></a>5.1 图的定义</h3><ul>
<li><p>1.标准定义</p>
<ul>
<li>图G图有顶点集V和边集E组成，记为G=(V,E), 其中V(G表示图G中顶点的有限非空集:，E(G)表示图G中顶点之间的关系(边)集合。若V={v1，v2，vn). 则用|V|表示图G中顶点的个数也称图 G的阶，E={(u,v)|u∈V,v∈V}.|E|表示图G中边的条数，</li>
<li>注意:线性表可以是空表、树可以是空树、但图不可以是空图</li>
</ul>
</li>
<li><p>2.其他常用定义</p>
<ul>
<li><p>无向图</p>
<ul>
<li><p>概念</p>
<ul>
<li><p>若E是无向边(简称边) 的有限集合时，则图G为无向图。边是顶点的无序对，记为(v,w)或(w,v)，因为(v,w)=(w,v), 其中v w是顶点。可以说顶点w和顶点v互为邻接点。</p>
<p>G2=(V2, E2)<br>V2= {1,2,3,4}<br>E2= {(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)}</p>
</li>
</ul>
</li>
<li><p>连通</p>
<ul>
<li>就是比如说两个顶点A跟B，A去B家有路线，但是B去A家没有</li>
</ul>
</li>
<li><p>连通图</p>
<ul>
<li>任意两个顶点都是连通的图</li>
</ul>
</li>
<li><p>连通分图</p>
</li>
</ul>
</li>
<li><p>有向图</p>
<ul>
<li><p>概念</p>
<ul>
<li><p>若E是有向边(也称弧)的有限集合时，则图G为有向图。弧是项点的有序对，记为<v,w>，其中v,w是顶点，<v,w>称为从顶点v到顶点w的弧</p>
<p>G1=(V,E)<br>V= {1,2,3}<br>E={<1,2>,<2.1>,<2,3>}</p>
</li>
</ul>
</li>
<li><p>连通</p>
<ul>
<li>就是比如说两个顶点A跟B，A去B家有路线，但是B去A家没有</li>
</ul>
</li>
<li><p>强连通图</p>
<ul>
<li>任意两个顶点都是连通的，还有就是A跟B两个家伙，现在是A可以去B家，B也可以去A家，两个条件</li>
</ul>
</li>
<li><p>强连通分量</p>
</li>
</ul>
</li>
<li><p>3.简单图</p>
<ul>
<li><p>一个图G是简单图的条件:</p>
<ul>
<li>①不存在重复边:</li>
<li>②不存在质点到自身的边</li>
</ul>
</li>
</ul>
</li>
<li><p>4.多重图</p>
<ul>
<li>若图G中某两个结点之间的边数多于一条，又允许顶点通过同一条边和自己关联，则G为多重图。多重图的定义和简单图是相对的。</li>
</ul>
</li>
<li><p>5.完全图(也称简单完全困)</p>
<ul>
<li>在无向图中，若任意两个顶点之间都存在边，则称该图为无向完全图。含有n个顶点的无向完全图有n(n-1)2条边。在有向图中，若任意两个顶点之间都存在方向相反的两条弧，则称该图为有向完全图。含有n个顶点的有向完全图有n(n-1)条有向边。</li>
</ul>
</li>
<li><p>6 子图</p>
<ul>
<li>设有俩个图G=(V,E)和G，且E是E的子集，则称G’是G的子图；若有满足V(G’)=V(G)的子图G’，则称G的生成子图</li>
</ul>
</li>
<li><p>7.连通、连通图和连通分量</p>
<ul>
<li>在无向图中，若从顶点v到顶点w有路径存在，则称v和w是联通的，若图G中任意两个顶点都是连通的，则图G为连通图，否则称为非连通图，无向图中的极大连通子围称为连通分量。若一个图有n个顶点，并且边数小于n-1，则此图必是非连通图。</li>
</ul>
</li>
<li><p>8强连通图、强连通分量</p>
<ul>
<li>在有向图中，若从顶点v到顶点w和从顶点w到项点v之间都有路径，则称这两个顶点是强连通,若图中任何一对顶点都是强连通，则称此图为强连通图。有向图中的极大强连通子图称为有向图的强连通分量</li>
</ul>
</li>
<li><p>9.生成树、生成森林</p>
<ul>
<li>连通图的生成树是包含图中全部顶点的一个极小连通子图。若图中顶点数为n，则它的生成树有n-1条边。对生成树而言,若砍去它的一条边,则会变成非连通图，若加上一条边，则会形成回路。在非连通图中,连通分量的生成树构成了非连通图的生成森林。</li>
</ul>
</li>
<li><p>10．顶点的度、入度和出度</p>
<ul>
<li>图中每个顶点的度定义为以该顶点为一个端点的边的数目。</li>
<li>对于无向图,顶点v的度是指依附于该顶点的边的条数,记为TD(v).</li>
<li>在具有n个顶点、e条边的无向图中,ΣTD(Vi)=2e,及无向图的全部顶点的度和和等于边数的2倍,因为每条边和两个顶点相关联。</li>
<li>对于有向图,顶点v的度分为入度和出度,入度是以顶点v为终点的有向边的数目,记为ID(v)，而出度是以顶点v为起点的有向边的数目，记为OD(v)，顶点v的度等于其入度和出度之和TD(v)=ID(v)+OD(v)</li>
<li>在具有n个顶点、e条边的有向图中,ΣID(vi)=ΣOD(vi)=e,即有向图入度和出度之和相等，并且等于边数。这是因为每条有同边都有一个起点和终点。</li>
</ul>
</li>
<li><p>11．边的权和网</p>
<ul>
<li>在一个图中,每条边都可以标上具有某种含义的数值，该数值称为该边的权值。这种边上有权值的图称为带权图,也称网。</li>
</ul>
</li>
<li><p>12．稠密图、稀疏图</p>
<ul>
<li>边数很少的图称为稀疏图,反之称为稠密图。稀坑和榈图个才龙快例的慨念，稀疏图和信e图常常是相对而言的。一般当图G满足|E&lt;|Vlog|V时,可以将G视为稀疏图。</li>
</ul>
</li>
<li><p>13．路径、路径长度和回路</p>
<ul>
<li>顶点vp到顶点vq之间的一条路径是指顶点序列vp,vl1,vl2.，…,vlm,vq。路径上边的数目称为路径长度。第一个顶点和最后一个顶点相同的路径称为回路或坏。右一个图有n个顶点，并且有大于n-1条边,则此图一定有环。</li>
</ul>
</li>
<li><p>14.简单路径、简单回路</p>
<ul>
<li>在路径序列中,顶点不重复出现的路径称为简单路径。除第一个顶点和最后一个顶点外，其余顶点不重复出现的回路称为简单回路。</li>
</ul>
</li>
<li><p>15.距离</p>
<ul>
<li>从顶点u出发到顶点v的最短路径若存在，则此路径的长度称为从u到v的距离。若从u到v根本不存在路径，则记该距离为无穷(∞)。</li>
</ul>
</li>
<li><p>16.有向树</p>
<ul>
<li>一个顶点的入度为0、 其余顶点的入度均为1的有向图， 称为有向树。</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="5-2-图的存储和基本操作"><a href="#5-2-图的存储和基本操作" class="headerlink" title="5.2 图的存储和基本操作"></a>5.2 图的存储和基本操作</h3><ul>
<li><p>5.2.1邻接矩阵法</p>
<ul>
<li>带权</li>
<li>不带权</li>
<li><p>邻接矩阵的存储结构定义</p>
<p>//顶点数目的最大值<br> define MaVertexNum 100<br>//顶点的数据类型<br>typedef char vertexType;<br>//带权图边上权值数据类型<br>typedef int EdgeType;<br>typedef struct{<br>//顶点表<br>VertexTvPe Vex[MaxVertexNum];<br>//邻接矩阵表示边<br>EdgeType Edge[MaxVertexNum][MaxVertexNum];<br>Int vexnum,arcnum;<br>}MGraph;</p>
<ul>
<li><p>注意:</p>
<ul>
<li>①在简单应用中,可直接用二维数组作为图的邻接矩阵,</li>
<li>②当邻接矩阵中的元素仅表示相应的边是否存在，EdgeType可定义为值为0 1的类型</li>
<li>③无向图的邻接矩阵是对称矩阵,对规模特大的邻接矩阵可以采用压缩存储</li>
<li>④邻接矩阵表示法的空间复杂度为O(n²),其中n为图的顶点数|V|。</li>
</ul>
</li>
<li><p>图的邻接矩阵存储表示法具有以下特点:</p>
<ul>
<li>1 无向图的邻接矩阵是一个对称矩阵并且唯一一，因此实际存储邻接矩阵时只需存储上(或下）三角矩阵的元素。</li>
<li>2 对于无向图，邻接矩阵的第i行（或第j列）的非零元素（非∞元素）的个数正好是第i个顶点的度TD(vi)</li>
<li>3 对于有向图，邻接矩阵的第i行（或第j列）的非零元素（非∞元素）的个数正好是第i个顶点的出度OD(vi)。</li>
<li>4 用邻接矩阵法存储图,很容易确定图中任意俩个顶点之间是否有边相连。但是，要确定途中有多少条边，则必须按行按列对每个元素进行检测，花费时间代价很大，这是用邻接矩阵存储图的局限性。</li>
<li>5 稠密图适合使用邻接矩阵的存储表示。</li>
<li>6 设图G的邻接矩阵为A,A”的元素A’’[i][j]等于由i到j的长度为n的路径的数目</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>5.2.2 邻接表</p>
<ul>
<li>我觉得是表示出度，用链表的方式表示该顶点能去哪</li>
<li><p>邻接表的特点</p>
<ul>
<li>对于有n个顶点和e条边的无向图，其邻接表有n个头结点和2e个边结点，对于有n个顶点和e条边的有向图其邻接表有n个头结点和e个边结点。显然，对于边数目较少的稀疏图，邻接表比邻接矩阵更节省存储空间。</li>
<li><p>对于无向图</p>
<ul>
<li>邻接矩阵数组的第i行或第i列非零元素，非无穷元素的个数正好是顶点i的度</li>
</ul>
</li>
<li><p>对于有向图</p>
<ul>
<li>邻接矩阵数组的第i行或（第i列）非零元素，非无穷元素的个数正好是顶点i的出度（或入度）</li>
</ul>
</li>
</ul>
</li>
<li><p>邻接表の实现</p>
<p>typedef struct ArcNode//弧结点<br>{</p>
<pre><code>int adjvex;//邻接点
struct ArcNode *nextarc;//洗一个邻接点
</code></pre><p>};<br>typedef struct vexNode<br>{</p>
<pre><code>vectex data;//顶点信息
ArcNode *firstarc;//第一个邻接点
</code></pre><p>};<br>typedef struct Graph<br>{</p>
<pre><code>vexNode vexs[MAX_VERTEX];
int vexnum, arcnum;
</code></pre><p>};</p>
</li>
<li><p>存储空间</p>
<ul>
<li><p>无向图</p>
<ul>
<li>O(|V|+2|E|)</li>
</ul>
</li>
<li><p>有向图</p>
<ul>
<li>O(|V|+|E|)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>5.2.3 十字链表</p>
<ul>
<li><p>定义</p>
<ul>
<li>一个二维十字链表是链表的元素同时链接左右水平邻结点与上下垂直邻结点</li>
</ul>
</li>
<li><p>实现</p>
<p>typedef struct OLNode {<br>   int LineNumber, ColumneNumber;     //行号与列号<br>   ElemType value;    //值<br>   struct OLNode <em>right, </em>down; //同行、同列下一个元素的指针<br>}OLNode, <em>OList;<br>typedef struct{<br>  OList </em>rhead, *chead;  //行和列链表头指针向量基址<br>  int mu,nu,tu;      //稀疏矩阵的行数，列数和非零元个数<br>}CrossList;</p>
</li>
</ul>
</li>
<li><p>5.2.4 临界多重表</p>
<ul>
<li><p>实现</p>
<p>//图中顶点数目的最大值<br>图的邻接多里衣仔循绐构定义如下:<br>define MaxVertexNum 100<br>//边表结点<br>typedef struct ArcNode {<br>//访问标记<br>bool mark<br>//分别指向该弧的两个结点<br>int ivex, jvex;<br>//分别指向两个顶点的下一条边<br>struct ArcNode <em>ilink, </em>jlink;<br>//相关信息指针<br>//InfoType info;<br>)ArcNode;<br>//顶点表结点<br>typedef struct VNode{<br>//顶点信息<br>VertexType data;<br>//指向第一条依附该顶点的边<br>ArcNode *firstedge;<br>vNode;<br>typedef struct{<br>//邻接表<br>VNode adjmulist [MaxVertexNum];<br>//图的顶点数和弧数<br>int vexnum, arcnum;<br>//AMLGraph是以邻接多重表存储的图类型<br>AMLGraph;</p>
</li>
</ul>
</li>
<li><p>5.2.5 图的基本操作</p>
<ul>
<li>Adjacent(G,x,y)判断图G是否存在边<x,y>或(x,y)</li>
<li>Neighbors(G,x)：列出G中与x临接的边</li>
<li>InsertVertex(G,x): 在G插入x</li>
<li>DeleteVertex(G,x): 在G删除x</li>
<li>AddEdge (G,x,y):若无向边(x,y)或有向边<x,y>不存在，则添加该边</li>
<li>RemoveEdge (G,x,y):若无向边(x,y)或有向边<x,y>存在，则删除该边</li>
<li>FirstNeighbor (G,x):求图G中x的第一个邻接点，若没有邻接点或图中不在在x,则返回-1。</li>
<li>NextNeighbor(G,x,y):假攻图G中顶点y是x的一个邻接点，则返回除y之外的x的下一个邻接点的顶点号,若y是x的最后一个邻接点，则返回-1</li>
<li>Get_edge_value(G,x,y)</li>
<li>Set_edge_value(G,X,y,V)</li>
</ul>
</li>
</ul>
<h3 id="图的遍历"><a href="#图的遍历" class="headerlink" title="图的遍历"></a>图的遍历</h3><ul>
<li>深度优先遍历</li>
<li>广度优先遍历</li>
</ul>
<h3 id="图的相关应用"><a href="#图的相关应用" class="headerlink" title="图的相关应用"></a>图的相关应用</h3><ul>
<li>最小生成树: Prim 算法、Kruskal 算让</li>
<li>最短路径: Dijkstr 算法、Floyd 算法</li>
<li>拓扑排序: AOV网</li>
<li>关键路径: AOE网</li>
</ul>
<h2 id="八、图"><a href="#八、图" class="headerlink" title="八、图"></a>八、图</h2><h3 id="图的遍历方式"><a href="#图的遍历方式" class="headerlink" title="图的遍历方式"></a>图的遍历方式</h3><ul>
<li><p>深度优先遍历</p>
<ul>
<li>步骤</li>
<li>void DFSTraverse(Graph G)<br>{<br>visited[0 ..G.vexnum - 1] = false;//初始化访问标记为未访问<br>for (v = 0; v &lt; G.vexnum; v++)<br>  if (!visited[v])DFS(G.v);//从未被访问的顶点开始<br>}<br>void DFS(Graph G, int v)<br>{<br>visit(v);//访问顶点v<br>visited[v] = true;<br>for (w = FistAdjVec(G.v); w &gt;= 0; w = NextAdjVex(G, v, w))<br>  if (!visited[w])DFS(G,w);<br>}</li>
</ul>
</li>
<li><p>广度优先遍历</p>
<ul>
<li><p>步骤</p>
<ul>
<li>(1)从某个顶点V出发，访问该顶点的所有邻接点V1，V2..VN</li>
<li>(2)从邻接点V1，V2…VN出发，再访问他们各自的所有邻接点</li>
<li>(3)重复上述步骤，直到所有的顶点都被访问过</li>
</ul>
</li>
<li><p>void BFSTraverse(Graph G)<br>{<br>visited[0 ..G.vexnum - 1] = false;//初始化访问标记为未访问<br>InitQueue(Q);<br>for (v = 0; v &lt; G.vexnum; v++)<br>  if (!visited[v])<br>  {</p>
<pre><code>  visit(v);
  visited[v] = true;
  EnQueue(Q, v);
  while(!)
  DFS(G.v);//从未被访问的顶点开始
</code></pre><p>  }<br>}<br>void BFS(Graph G, int v)<br>{<br>visit(v);//访问顶点v<br>visited[v] = true;<br>for (w = FistAdjVec(G.v); w &gt;= 0; w = NextAdjVex(G, v, w))<br>  if (!visited[w])DFS(G, w);<br>}</p>
</li>
</ul>
</li>
</ul>
<h3 id="图的应用"><a href="#图的应用" class="headerlink" title="图的应用"></a>图的应用</h3><ul>
<li><p>最小生成树</p>
<ul>
<li>边上的权值之和最小的树称图的最小生成树</li>
<li><p>Prim算法</p>
<ul>
<li>选定以某个顶点开始，去找各顶点上最小权值的边来构建最小生成树。选取A为起点，最小生成树序列应该是这样的：<A,B>,<B,C>,<C,E>,到这里是怎样，是接着从E这个顶点出发，选取E邻边权值最小的边，还是直接选取另外一个顶点作为起点开始？</li>
<li></li>
</ul>
</li>
<li><p>Krustra算法</p>
<ul>
<li>直接去找最小的那条边，不用连着去找，</li>
<li></li>
</ul>
</li>
</ul>
</li>
<li><p>拓补排序</p>
<ul>
<li>在一个有向图中找一个拓扑序列的过程叫拓扑排序</li>
<li><p>步骤</p>
<ul>
<li>每次找一个没有前驱结点的顶点，并删除它，重复做这件事，如果有删除不了的顶点，表明有回路（就是找不到没有前驱结点的结点）</li>
</ul>
</li>
</ul>
</li>
<li><p>关键路径</p>
<ul>
<li>在AOE网中，从源点到汇点的所有路径中具有最大路径长度的路径称为关键路径</li>
<li>AOE：</li>
<li><p>源点</p>
<ul>
<li>入度为0的顶点（我理解为像线性表的表头结点，没有前驱结点的结点）</li>
</ul>
</li>
<li><p>汇点</p>
<ul>
<li>出度为0的顶点（没有后继的结点）</li>
</ul>
</li>
<li><p>最短路径</p>
<ul>
<li><p>不带权图</p>
<ul>
<li>经过的边数最少的路径称为最短路径。</li>
</ul>
</li>
<li><p>带权图</p>
<ul>
<li>所经过的边权值之和最小的路径称为最短路径</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="问题-3"><a href="#问题-3" class="headerlink" title="问题"></a>问题</h3><ul>
<li><p>1、G是一个非连通无向图，共有28条边，则该图至少有（B）个顶点。<br>A、8   B、9   C、10    D、11<br>解释：<br>2、设G是一个非连通无向图，有15条边，则该图至少有()个顶点。<br>A、5   B、6   C、7   D、15<br>解释：要使顶点个数最少并且为非连通无向图，图 由两个连通分量构成:完全无向图+单个顶点。完全无向图:n(n-1)/2＝15中n＝6。单个顶点:1个顶点。应的图有6+1＝7个顶点<br>3、若无向图G(V，E)中含7个顶点，则保证图G在任何情况下都是连通的，则需要的边数最少是（ ）。<br>A. 6   B. 15      C. 16            D. 21<br>解释：对于具有n个顶点的无向图，当其中n-1个顶点构成一个完全图时，再加上一条边（连接该完全图和另外一个顶点）必然构成一个连通图所以本题中，若 6个顶点构成一个完全图，再加上一条边，这样的图无论如何都是一个连通图。最少边数=[(n-1)(n-2)/2]+1=16<br>4、设有6个结点的无向图，该图至少应有（A）条边才能确保是一个连通图。<br>A、5   B、6   C、7   D、8<br>5、具有7个顶点的有向图至少应有（B）条边才可能成为一个强连通图?<br>A、6   B、7   C、8   D、12<br>6、一个非连通图(无自回路和多重边)有66条边,那么它至少有(C)个顶点<br>A、11    B、12    C、13    D、14<br>​<br>7、设无向图G中有n个顶点e条边，则其对应的邻接表中的表头结点和表结点的个数分别为（ D ）<br>A、n，e     B e，n     C)2n，e    D n，2e<br>解释：看下图<br>8、设有向图G中有n个顶点e条边，则其对应的邻接表中的表头结点和表结点的个数分别为（A ）<br>A、n，e     B e，n     C)2n，e    D n，2e<br>解释：看下图<br>9、含n个顶点的无向连通图中至少含有（n-1)条边。<br>10、 在一个具有n个顶点的无向完全图中，包含有n(n-1)/2条边，在一个具有n个顶点的有向完全图中，包含有n(n-1)条边<br>​<br>11、设有6个结点的无向图，该图至少应有(      )条边才能确保是一个连通图。<br>A.5       B.6         C.7      D.8<br>解释：</p>
<p>12、  若用链表存储一棵二叉树时，每个结点除数据域外，还有指向左孩子和右孩子的两个指针。在这种存储结构中，n个结点的二叉树共有<strong>____</strong>个指针域，其中有<strong>____</strong>个指针域是存放了地址，有<strong><strong><strong>____</strong></strong></strong>个指针是空指针。</p>
</li>
</ul>
<p>13、 设某棵二叉树中度数为0的结点数为N0，度数为1的结点数为N1，则该二叉树中度数为2的结点数为<strong><strong>_</strong></strong>；若采用二叉链表作为该二叉树的存储结构，则该二叉树中共有<strong>___</strong>个空指针域。<br>​<br>14、设无向图对应的邻接矩阵为A，则A中第i上非0元素的个数（等于）第i列上非0元素的个数<br>​<br>15、设某无向图G中有n个顶点，用邻接矩阵A作为该图的存储结构，则顶点i和顶点j互为邻接点的条件是（A[i][j]=1）<br>​<br>16、 设有向图G的存储结构用邻接矩阵A来表示，则A中第i行中所有非零元素个数之和等于顶点i的（出度），第i列中所有非零元素个数之和等于顶点i的（入度）；<br>解释：看上图邻接矩阵的表示</p>
<h2 id="六：数组和广义表"><a href="#六：数组和广义表" class="headerlink" title="六：数组和广义表"></a>六：数组和广义表</h2><h3 id="数组："><a href="#数组：" class="headerlink" title="数组："></a>数组：</h3><ul>
<li><p>数组的存储结构</p>
<ul>
<li>一维数组的存储结构</li>
<li>二维数组的存储结构</li>
<li><p>按行优先存放</p>
<ul>
<li>按行优先存放，第一个元素地址为a0的话，有LOC(ai，j)=LOC(a0，0)+(i×n+j)×k；</li>
<li>按行优先存放，第一个元素地址为a1的话，有LOC(ai，j)=LOC(a1，1)+[(i-1)×n+(j-1)]×k</li>
</ul>
</li>
<li><p>按列优先存放</p>
<ul>
<li>按列优先存放，第一个元素地址为a0的话，有LOC(ai，j)=LOC(a0，0)+(j×m+i)×k；</li>
<li>按列优先存放，第一个元素地址为a1的话，有LOC(ai，j)=LOC(a1，1)+[(j-1)×n+(i-1)]×k</li>
</ul>
</li>
<li><p>特殊矩阵的压缩存储（什么是特殊矩阵呢？就是非零元素和零元素的分布有规律（对称,上三角，下三角，对角矩阵）的叫特殊矩阵）</p>
<ul>
<li>对称矩阵</li>
<li>上三角矩阵</li>
<li>下三角矩阵</li>
<li>对角矩阵</li>
</ul>
</li>
<li><p>稀疏矩阵的压缩存储（上面有特殊矩阵，这个其实就跟特殊矩阵相反的吧，就是非零元素和零元素的分布没有规律），稀疏矩阵的两种压缩存储方式会使数组失去随机存储性</p>
<ul>
<li>三元组表</li>
<li>十字链表</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="广义表"><a href="#广义表" class="headerlink" title="广义表"></a>广义表</h3><ul>
<li>广义表中的数据元素是有相对次序的</li>
<li>广义表的长度定义为最外层包含元素个数</li>
<li>广义表的深度定义为所含括弧的重数（其实就是从左到右数左括号的数量就是深度），原子的深度为0，空表的深度为1</li>
<li>广义表的长度，指的是广义表中所包含的数据元素的个数。</li>
<li>由于广义表中可以同时存储原子和子表两种类型的数据，因此在计算广义表的长度时规定，广义表中存储的每个原子算作一个数据，同样每个子表也只算作是一个数据。（所以一个数据长度就为1）</li>
<li>总结：当问到广义表长度时，看有多少个数据就好了，虽然有点说废话，但是说这话之前，我确实不知道这回事，嘻嘻</li>
<li>广义表的深度，可以通过观察该表中所包含括号的层数间接得到。</li>
<li><p>广义表的存储结构</p>
<ul>
<li>链式存储结构</li>
</ul>
</li>
</ul>
<h2 id="七：树和二叉树"><a href="#七：树和二叉树" class="headerlink" title="七：树和二叉树"></a>七：树和二叉树</h2><h3 id="特点：非线性结构，一个直接前驱和n个直接后缀"><a href="#特点：非线性结构，一个直接前驱和n个直接后缀" class="headerlink" title="特点：非线性结构，一个直接前驱和n个直接后缀"></a>特点：非线性结构，一个直接前驱和n个直接后缀</h3><h3 id="6-1树的定义和基本术语"><a href="#6-1树的定义和基本术语" class="headerlink" title="6.1树的定义和基本术语"></a>6.1树的定义和基本术语</h3><ul>
<li><p>树的定义</p>
<ul>
<li><p>（一）概述</p>
<ul>
<li>  树是一种非常适合查找的数据结构，掌握树这种数据结构非常重要，树这种数据结构需要使用递归算法，所以在学习树之前，了解递归的思想非常重要，这里不展开详述，只提一点：理解递归时，切忌陷入程序递归的内部去思考递归算法，记住要从递归思维的本质(复杂问题简单化)出发去理解递归算法，千万不要去通过试图解析程序执行的每一个步骤来理解递归（解析程序的执行是指给函数一个真实值，然后自己一步步去推出结果，这样的思考方式是错误的！）。</li>
<li>  所谓查找就是根据某个给定关键字K，从集合R中找出关键字与K相同的记录，查找又分为静态查找和动态查找：</li>
<li><p>静态查找</p>
<ul>
<li>集合中记录是固定的，即没有插入和删除操作，只有查找</li>
</ul>
</li>
<li><p>动态查找</p>
<ul>
<li>集合中记录是动态变化的，除查找外，还有插入和删除操作</li>
</ul>
</li>
</ul>
</li>
<li><p>（二）定义</p>
<ul>
<li><p>  树：n(n≥0)个结点构成的有限集合。</p>
<ul>
<li>    当n=0时，称为空树。</li>
<li>    对于任何一颗非空树，其子树(SubTree)之间互不相交，每棵树有且只有一个最顶层的结点被称作根(root)。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>若干术语</p>
<ul>
<li><p>边(edge)：</p>
<ul>
<li>  结点与结点之间是通过一条有向的边(edge)所连接的，一颗结点为n的树有n-1条边，因为除去根结点没有边，其余的结点都有一条边；</li>
</ul>
</li>
<li><p>结点的度(degree)：</p>
<ul>
<li>  结点的子树个数，比如上图B的度为3，C的度为1，E的度为0；</li>
</ul>
</li>
<li><p>树的度：</p>
<ul>
<li>  树的所有结点中最大的度数；</li>
</ul>
</li>
<li><p>叶结点(leaf)：</p>
<ul>
<li>  度为0的结点；</li>
</ul>
</li>
<li><p>父结点(parent):</p>
<ul>
<li>  有子树的结点是其子树的根结点的父结点（双亲）；</li>
</ul>
</li>
<li><p>子结点(child)：</p>
<ul>
<li>  若A结点是B结点的父结点，则称B结点是A结点的子结点；子结点也称孩子结点；</li>
</ul>
</li>
<li><p>兄弟结点(sibling)：</p>
<ul>
<li>  具有同一父结点的各结点之间彼此为兄弟结点；</li>
</ul>
</li>
<li><p>路径和路径长度：</p>
<ul>
<li>  从结点n1到结点nk的路径为一个结点序列n1，n2，…，nk，ni是ni+1的父结点，路径所包含的边的个数为路径的长度；</li>
</ul>
</li>
<li><p>祖先结点(ancestor)：</p>
<ul>
<li>  沿树根到某一结点路径上的所有结点都是这个结点的祖先结点；</li>
</ul>
</li>
<li><p>子孙结点(ancestor)：</p>
<ul>
<li>  某一结点的子树中的所有结点是这个结点的子孙；</li>
</ul>
</li>
<li><p>结点的层次(level)：</p>
<ul>
<li>  结点的层次是从根开始定义的，规定根结点在1层，其他任一结点的层数是其父结点的层数加1（又是递归）；</li>
</ul>
</li>
<li><p>结点的高度(《数据结构与算法分析——C语言描述》定义)：</p>
<ul>
<li>  对任意结点ni，ni的深度为从根到ni的唯一路径的长，ni的高度为从ni到叶结点的最长路径长，因此，任何叶结点的高度为0；</li>
</ul>
</li>
<li><p>树的深度(depth)：</p>
<ul>
<li>  树中结点的最大层次称为树的深度(depth)或高度，注意，不同的教材对这两个名词的定义不一样，《数据结构与算法分析——C语言描述》里为这里定义的高度-1；</li>
</ul>
</li>
<li><p>森林(forest)：</p>
<ul>
<li>  互不相交的树的集合，对数中的每个结点而言，其子树的集合即为森林。</li>
<li>  注意，国内关于树的深度（或高度）的定义和国外的不一样，这里采用的是国内的定义方式，国外的定义可以参考《数据结构与算法分析——C语言描述》这本书。</li>
</ul>
</li>
</ul>
</li>
<li><p>存储结构</p>
<ul>
<li><p>1、双亲表示法</p>
<ul>
<li><p>实现：定义一个结构数组存放树的结点，每个结点含两个域，可以按层存储，</p>
<ul>
<li>   - 数据域：存放结点本身的信息；</li>
<li>   - 双亲域：指示本结点的双亲结点在数组中的位置。</li>
</ul>
</li>
<li><p>特点：方便寻找双亲，但是找子结点很困难。</p>
</li>
<li>/<em>定义结点</em>/<br>typedef struct node{<br>element data;<br>int parent;<br>}TreeNode;</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>/<em>定义树</em>/<br>TreeNode tree[M];</p>
<pre><code>- 2、孩子表示法

    - 实现：使用了多重链表
    - /*孩子结点*/
</code></pre><p>typedef struct childNode{<br>    int child;//该结点在表头数组中的下标<br>    struct childNode* next;//指向下一个孩子结点<br>};</p>
<p>/<em>表头结点</em>/<br>typedef struct headNode{<br>    element data;//数据域<br>    struct childNode* fc;//指向第一个孩子结点<br>};</p>
<p>headNode t[M];//t[0]不用</p>
<pre><code>- 3、孩子兄弟表示法(二叉树表示法)

    - 实现：用二叉链表作为树的存储结构，链表中每个结点的两个指针域分别指向其第一个孩子结点和下一个兄弟结点。
    - 特点：操作容易，破坏了树的层次。
    - /*儿子兄弟表示法*/
</code></pre><p>typedef struct node{<br>    element data;//数据域<br>    struct node<em> firstChild;//第一个儿子结点<br>    struct node</em> siblingChild;//其兄弟结点<br>};</p>
<pre><code>- #include &lt;stdio.h&gt;
</code></pre><h1 id="include-2"><a href="#include-2" class="headerlink" title="include "></a>include <malloc.h></h1><h1 id="include-“GTree-h”"><a href="#include-“GTree-h”" class="headerlink" title="include “GTree.h”"></a>include “GTree.h”</h1><h1 id="include-“LinkList-h”"><a href="#include-“LinkList-h”" class="headerlink" title="include “LinkList.h”"></a>include “LinkList.h”</h1><p>typedef struct _tag_GTreeNode GTreeNode;  /<em> 树的节点 </em>/<br>struct _tag_GTreeNode<br>{<br>    GTreeData<em> data;   /</em> 节点自身数据 <em>/<br>    GTreeNode</em> parent;  /<em> 父亲节点 </em>/<br>    LinkList<em> child;   /</em> 孩子链表 */<br>};</p>
<p>typedef struct _tag_TLNode TLNode;   /<em> 链表节点结构体，将树节点串成链表 </em>/<br>struct _tag_TLNode<br>{<br>    LinkListNode header;<br>    GTreeNode* node;<br>};</p>
<p>static void recursive_display(GTreeNode<em> node, GTree_Printf</em> pFunc, int format, int gap, char div)/<em> 递归打印函数 定义为static外界看不到  format—缩进单位个数  gap—缩进单位 div—缩进形式 pFunc—打印函数</em>/<br>{<br>    int i = 0;</p>
<pre><code>if( (node != NULL) &amp;&amp; (pFunc != NULL) )
&#123;
    for(i=0; i&lt;format; i++)
    &#123;
        printf(&quot;%c&quot;, div);
    &#125;

    pFunc(node-&gt;data);  /* 打印数据 */

    printf(&quot;\n&quot;);

    for(i=0; i&lt;LinkList_Length(node-&gt;child); i++)
    &#123;
        TLNode* trNode = (TLNode*)LinkList_Get(node-&gt;child, i);

        recursive_display(trNode-&gt;node, pFunc, format + gap, gap, div);
    &#125;
&#125;
</code></pre><p>}</p>
<p>static void recursive_delete(LinkList<em> list, GTreeNode</em> node)   /<em> 递归删除函数 要删除该节点的所有函数 </em>/<br>{<br>    if( (list != NULL) &amp;&amp; (node != NULL) )<br>    {<br>        GTreeNode<em> parent = node-&gt;parent;  /</em> 要删除的节点的父亲节点 */<br>        int index = -1;<br>        int i = 0;</p>
<pre><code>    for(i=0; i&lt;LinkList_Length(list); i++)   /* 从树的组织链表中删除该节点 */
    &#123;
        TLNode* trNode = (TLNode*)LinkList_Get(list, i);

        if( trNode-&gt;node == node )
        &#123;
            LinkList_Delete(list, i);

            free(trNode);

            index = i;  /* 标记位：表面从组织链表中删除成功 */

            break;
        &#125;
    &#125;

    if( index &gt;= 0 )
    &#123;
        if( parent != NULL )   /* 从父亲节点的孩子链表中删除该节点  */
        &#123;
             for(i=0; i&lt;LinkList_Length(parent-&gt;child); i++)
             &#123;
                 TLNode* trNode = (TLNode*)LinkList_Get(parent-&gt;child, i);

                 if( trNode-&gt;node == node )
                 &#123;
                     LinkList_Delete(parent-&gt;child, i);

                     free(trNode);

                     break;
                 &#125;
             &#125;
        &#125;

        while( LinkList_Length(node-&gt;child) &gt; 0 )  /* 删除要删除的节点的孩子节点 */
        &#123;
            TLNode* trNode = (TLNode*)LinkList_Get(node-&gt;child, 0);  /* 从孩子链表中一个一个取出来 递归删除所有孩子节点 */

            recursive_delete(list, trNode-&gt;node);
        &#125;

        LinkList_Destroy(node-&gt;child);  /* 销毁要删除节点的孩子链表 */

        free(node);  /* 将insert申请的内存释放 */
    &#125;
&#125;
</code></pre><p>}</p>
<p>static int recursive_height(GTreeNode<em> node)   /</em> 递归算出树的高度 计算一个树的高度首先要算出子树的高度后+1 */<br>{<br>    int ret = 0;</p>
<pre><code>if( node != NULL )
&#123;
    int subHeight = 0;
    int i = 0;

    for(i=0; i&lt;LinkList_Length(node-&gt;child); i++)
    &#123;
        TLNode* trNode = (TLNode*)LinkList_Get(node-&gt;child, i);  /* 从链表中取出子树的根节点 */

        subHeight = recursive_height(trNode-&gt;node);

        if( ret &lt; subHeight )
        &#123;
            ret = subHeight;
        &#125;
    &#125;

    ret = ret + 1;  /*  加上根节点 故要+1 */
&#125;

return ret;
</code></pre><p>}</p>
<p>static int recursive_degree(GTreeNode<em> node)   /</em> 定义静态函数 外部无法看到  递归算出 */<br>{<br>int ret = -1;</p>
<pre><code>if( node != NULL )
&#123;
    int subDegree = 0;
    int i = 0;

    ret = LinkList_Length(node-&gt;child);

    for(i=0; i&lt;LinkList_Length(node-&gt;child); i++)
    &#123;
        TLNode* trNode = (TLNode*)LinkList_Get(node-&gt;child, i);

        subDegree = recursive_degree(trNode-&gt;node);

        if( ret &lt; subDegree )   /* 取最大值 */
        &#123;
            ret = subDegree;
        &#125;
    &#125;
&#125;

return ret;
</code></pre><p>}</p>
<p>GTree* GTree_Create()<br>{<br>    return LinkList_Create();<br>}</p>
<p>void GTree_Destroy(GTree<em> tree)  /</em> 此处数据封装 用户表面看起来只是一个tree(实际为一个单链表) */<br>{<br>    GTree_Clear(tree);<br>    LinkList_Destroy(tree);<br>}</p>
<p>void GTree_Clear(GTree<em> tree)<br>{<br>     GTree_Delete(tree, 0);   /</em> 删除根节点就相当于删除整个树 */<br>}</p>
<p>int GTree_Insert(GTree<em> tree, GTreeData</em> data, int pPos)   /<em> pPos—-代表要插入的数据的父亲在表中的位置 </em>/<br>{<br>    LinkList<em> list = (LinkList</em>)tree;<br>    int ret = (list != NULL) &amp;&amp; (data != NULL) &amp;&amp; (pPos &lt; LinkList_Length(list));  /<em> 合法性检测 pPos至少小于树节点(链表)长度 </em>/</p>
<pre><code>if( ret )
&#123;
    TLNode* trNode = (TLNode*)malloc(sizeof(TLNode));  /* (树)组织节点 */
    TLNode* cldNode = (TLNode*)malloc(sizeof(TLNode));  /* child节点  *---插入某个节点时，要将其插入两个链表，一个是组织链表，一个是父亲节点的子节点链表 */
    TLNode* pNode = (TLNode*)LinkList_Get(list, pPos);   /* 从树中(链表)中取出pPos位置的节点 强制转换为TLnode---里面有指向树节点的指针 */
    GTreeNode* cNode = (GTreeNode*)malloc(sizeof(GTreeNode));   /* 申请一个树节点 */

    ret = (trNode != NULL) &amp;&amp; (cldNode != NULL) &amp;&amp; (cNode != NULL);

    if( ret )
    &#123;
        cNode-&gt;data = data;   /* 对新创建的通用节点赋值 */
        cNode-&gt;parent = NULL;   /* 暂时指定该节点没有双亲 */
        cNode-&gt;child = LinkList_Create();

        trNode-&gt;node = cNode;
        cldNode-&gt;node = cNode;

        LinkList_Insert(list, (LinkListNode*)trNode, LinkList_Length(list));  /* 插入到组织链表中 */

        if( pNode != NULL )  /* 根节点没有双亲 故此处要判断 */
        &#123;
            cNode-&gt;parent = pNode-&gt;node;  /* 将申请的节点赋给父亲节点 */

            LinkList_Insert(pNode-&gt;node-&gt;child, (LinkListNode*)cldNode, LinkList_Length(pNode-&gt;node-&gt;child));  /* 插入到父亲节点的孩子链表中 */
        &#125;
    &#125;
    else
    &#123;
        free(trNode);
        free(cldNode);
        free(cNode);
    &#125;
&#125;

return ret;
</code></pre><p>}</p>
<p>GTreeData<em> GTree_Delete(GTree</em> tree, int pos)<br>{<br>    TLNode<em> trNode = (TLNode</em>)LinkList_Get(tree, pos);<br>    GTreeData<em> ret = NULL;   /</em> 要删除的节点里保存的数据 */</p>
<pre><code>if( trNode != NULL )
&#123;
    ret = trNode-&gt;node-&gt;data;

    recursive_delete(tree, trNode-&gt;node);  /* 递归删除，要删除所有孩子 */
&#125;

return ret;
</code></pre><p>}</p>
<p>GTreeData<em> GTree_Get(GTree</em> tree, int pos)   /<em> 从组织链表中pos节点的数据返回 </em>/<br>{<br>    TLNode<em> trNode = (TLNode</em>)LinkList_Get(tree, pos);<br>    GTreeData* ret = NULL;</p>
<pre><code>if( trNode != NULL )
&#123;
    ret = trNode-&gt;node-&gt;data;
&#125;

return ret;
</code></pre><p>}</p>
<p>GTreeData<em> GTree_Root(GTree</em> tree)<br>{<br>    return GTree_Get(tree, 0);<br>}</p>
<p>int GTree_Height(GTree<em> tree)<br>{<br>    TLNode</em> trNode = (TLNode*)LinkList_Get(tree, 0);<br>    int ret = 0;</p>
<pre><code>if( trNode != NULL )
&#123;
    ret = recursive_height(trNode-&gt;node);
&#125;

return ret;
</code></pre><p>}</p>
<p>int GTree_Count(GTree* tree)<br>{<br>    return LinkList_Length(tree);<br>}</p>
<p>int GTree_Degree(GTree<em> tree)<br>{<br>    TLNode</em> trNode = (TLNode*)LinkList_Get(tree, 0);<br>    int ret = -1;</p>
<pre><code>if( trNode != NULL )
&#123;
    ret = recursive_degree(trNode-&gt;node);
&#125;

return ret;
</code></pre><p>}</p>
<p>void GTree_Display(GTree<em> tree, GTree_Printf</em> pFunc, int gap, char div)<br>{<br>    TLNode<em> trNode = (TLNode</em>)LinkList_Get(tree, 0);</p>
<pre><code>if( (trNode != NULL) &amp;&amp; (pFunc != NULL) )
&#123;
    recursive_display(trNode-&gt;node, pFunc, 0, gap, div);
&#125;
</code></pre><p>}</p>
<ul>
<li>树的运算</li>
</ul>
<h3 id="6-2二叉树"><a href="#6-2二叉树" class="headerlink" title="6.2二叉树"></a>6.2二叉树</h3><ul>
<li><p>定义</p>
<ul>
<li>二叉树（BinaryTree)是n个有限结点的有限集合，集合可为空，或由根节点和两科互不相交的子树构成，其子树也是二叉树，因此二叉树具有递归结构。</li>
</ul>
<p>二叉树的基本形态：</p>
</li>
<li><p>性质</p>
<ul>
<li>1.在二叉树的第i层上至多有 2i-1 个结点（i ≥ 1）。</li>
<li>2.高度为h的二叉树上最多有2h-1个结点（h≥1）。</li>
<li>3.任意一棵二叉树中，若叶子结点的个数为n0,度为1的结点的个数为n1,度为2的结点的个数为n2,则有n0=n2+1。</li>
<li>4.包含n个结点的二叉树的高度值最小为┍ log2(n+1) ┑(向上取整）,最大为n。</li>
</ul>
</li>
<li><p>存储结构</p>
<ul>
<li><p>满二叉树：</p>
<ul>
<li>在一颗二叉树中，所有的叶子结点都在二叉树的同一层上，除了叶子结点外，所有的分支结点都有两棵子树，这样的二叉树称为满二叉树。</li>
</ul>
</li>
<li><p>完全二叉树：</p>
<ul>
<li>只有最下面两层结点的度可以小于2，且最下面一层的叶子结点编号连续集中在靠左的位置上的二叉树成为完全二叉树。</li>
</ul>
</li>
<li><p>假定对一棵有n个结点的完全二叉树中的结点，按层次从上到下、每层结点从左到右的顺序，从0到n-1编号（如上图），设图中某个结点的编号为i，则有</p>
<ul>
<li>1）当i=0，该结点无双亲，为二叉树的根；当i&gt;0时，该结点的双亲结点编号为└ (i-1）/2┘（向下取整）</li>
<li>2）若 2i+1&lt;n，则其左孩子存在并且其编号为2i+1；否则该结点无左孩子</li>
<li>3）若 2(i+1)&lt;n，则其右孩子存在并且其编号为2(i+1)；否则该结点无右孩子</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="6-3遍历二叉树和线索二叉树"><a href="#6-3遍历二叉树和线索二叉树" class="headerlink" title="6.3遍历二叉树和线索二叉树"></a>6.3遍历二叉树和线索二叉树</h3><h3 id="6-4树和森林"><a href="#6-4树和森林" class="headerlink" title="6.4树和森林"></a>6.4树和森林</h3><h3 id="6-5赫夫曼编码及其应用"><a href="#6-5赫夫曼编码及其应用" class="headerlink" title="6.5赫夫曼编码及其应用"></a>6.5赫夫曼编码及其应用</h3><h3 id="树"><a href="#树" class="headerlink" title="树"></a>树</h3><ul>
<li><p>概念</p>
<ul>
<li><p>三、树的存储结构</p>
<ul>
<li>双亲表示法</li>
<li>孩子表示法</li>
<li>孩子兄弟表示法</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h3><ul>
<li><p>二叉树概念</p>
<ul>
<li><p>会经常考查树和二叉树的性质</p>
<ul>
<li><p>若一颗3次数树中度为3的结点有两个，度为2的结点有一个，度为1的结点有两个，则该3次数中总的结点个数和叶子节点个数分别是多少？(是不是度为5的结点有6个，是不是该表示为：5*n5)</p>
<ul>
<li>设该3次数中总的结点个数为n,度为i的结点个数为ni(0&lt;=i&lt;=3).依题意有n1=2,n2=1,n3=2;<br>每个度为i的结点在所有结点度数之和中贡献i个度，所以所有结点度数之和 = 1<em>n1+2</em>n2+3<em>n3 = 1</em>2+2<em>1+3</em>2 = 10;<br>由树的性质1可知，n=所有结点度数之和+1 =10+1 = 11；<br>对于3次树，显然有n = n0+n1+n2+n3。<br>则n0 = n-n1-n2-n3 = 11-2-1-2 =6;<br>所以该3次树中总的结点个数和叶子节点个数分别是11和6；</li>
</ul>
</li>
</ul>
</li>
<li><p>二叉树的存储结构</p>
<ul>
<li><p>顺序存储结构</p>
<ul>
<li>可以用数组表示，下标存储对应编号的结点，如果是空的结点，可以用#表示，</li>
</ul>
</li>
<li><p>链式存储结构</p>
<ul>
<li>二叉树的每个结点用链表中的一个结点来存储，二叉链存储结构下图。data表示值域，用于存储对应的数据元素，lchild和rchild分别表示左指针域和右指针域，分别用于存储左孩子结点和右孩子结点的存储地址</li>
</ul>
</li>
</ul>
</li>
<li><p>二叉树的构造</p>
</li>
</ul>
</li>
<li><p>二叉树操作</p>
<ul>
<li><p>创建</p>
<ul>
<li>typedef struct BitNode<br>{<br>TElemType data;<br>struct BitNode <em>lchild, </em>rchild;<br>}BitNode,*BiTree;</li>
</ul>
</li>
<li><p>二叉树遍历</p>
<ul>
<li><p>二叉树遍历案例一:</p>
<ul>
<li></li>
</ul>
</li>
<li><p>前序遍历：ABDFGHIEC</p>
<ul>
<li>递归算法</li>
<li><p>非递归算法</p>
<ul>
<li>void PreorderTraverse(Bitree T)<br>{<br>InitStack(s);<br>BiTree p=T;<br>while (p != NULL || !Emptystack(s))<br>{<br>if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子<br>{<br>visit(p);<br>Push(s, p);<br>p = p-&gt;left;<br>}<br>else//当他完成遍历后，去遍历其右孩子<br>{<br>Pop(s, p); p = p-&gt;right;<br>}<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>中序遍历：FDHGIBEAC（有点像从下往上的感觉）</p>
<ul>
<li><p>非递归算法</p>
<ul>
<li>void InorderTraverse(Bitree T)<br>{<br>InitStack(s);<br>Push(s, T);<br>while (!Emptystack(s))<br>{<br>while (GetTop(s, p) &amp;&amp; p)//向左走到尽头<br>Push(s.p-&gt;lchild);<br>Pop(s, p);<br>if (!Emptystack(s))//得到一个新节点，访问后压入栈中，之后访问他的左孩子<br>{<br>Pop(s, p);<br>visit(p);<br>Push(s, p-&gt;rchild);<br>}<br>}<br>}</li>
<li>void InorderTraverse(Bitree T)<br>{<br>InitStack(s);<br>BiTree p = T;<br>while (p != NULL || !Emptystack(s))<br>{<br>if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子<br>{<br>Push(s, p);<br>p = p-&gt;left;<br>}<br>else//当他完成遍历后，去遍历其右孩子<br>{<br>Pop(s, p);<br>visit(p);<br>p = p-&gt;right;<br>}<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>后序遍历：FHIGDEBCA</p>
<ul>
<li><p>已知先序遍历与后序遍历</p>
<ul>
<li><p>序列刚好相反</p>
<ul>
<li>不可能同时有左右节点</li>
</ul>
</li>
</ul>
</li>
<li><p>非递归算法</p>
<ul>
<li>void PreorderTraverse(Bitree T)<br>{<br>InitStack(s);<br>BiTree p = T,r=NULL;</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>while (p != NULL || !Emptystack(s))<br>{<br>  if (p != NULL)//得到一个新节点，访问后压入栈中，之后访问他的左孩子<br>  {</p>
<pre><code>  Push(s, p);
  p = p-&gt;left;
</code></pre><p>  }<br>  else//不能直接退栈<br>  {</p>
<pre><code>  getTop(s, p);
  if (p-&gt;right != NULL&amp;&amp;p-&gt;right != r)p = p-&gt;right;
  else
  &#123;
      Pop(s, p); visit(p); r = p; p = NULL;
  &#125;
</code></pre><p>  }<br>}<br>}</p>
</li>
</ul>
</li>
</ul>
<pre><code>- 编写求二叉树的叶子节点的算法
- 求二叉树的深度
- 由遍历序列恢复二叉树
</code></pre><ul>
<li><p>二叉树类型</p>
<ul>
<li><p>六、线索二叉树</p>
<ul>
<li>线索二叉树就是比二叉链多加了前驱和后继。</li>
</ul>
</li>
<li><p>二叉排序树</p>
<ul>
<li><p>思路</p>
<ul>
<li>二叉树为空，则找不到</li>
<li>先于跟比较，相等则找到</li>
<li>否则弱小于根则在左子树寻找否则右子树</li>
</ul>
</li>
<li><p>递归</p>
<ul>
<li>BiTree BitSearch(BiTree bt, TElemType x)<br>{<br>if (bt == NULL)return NULL;<br>else if (bt-&gt;data == x)return bt;<br>else if (bt-&gt;data &lt; x)return BitSearch(bt-&gt;lchild, x);<br>else if (bt-&gt;data &gt; x)return BitSearch(bt-&gt;rchild, x);<br>}</li>
</ul>
</li>
<li><p>非递归</p>
<ul>
<li>BiTree BitSearch(BiTree bt, TElemType x)<br>{<br>p = bt;<br>while (p)<br>{<br>if (p-&gt;data == x)return p;<br>else if (p-&gt;data &lt; x)return p = p-&gt;lchild;<br>else if (p-&gt;data &gt; x)return p = p-&gt;rchild;<br>}<br>return NULL;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>二叉树用途</p>
<ul>
<li><p>八、哈夫曼树和哈弗曼编码</p>
<ul>
<li>1、设有一棵哈夫曼树的结点总数为35，则该哈夫曼树共有（A）个叶子结点。<br>A. 18                B. 20                C. 35                    D. 30</li>
<li>2、设哈夫曼树中共有99个结点，则该树中有(50)个叶子结点；若采用二叉链表作为存储结构，则该树中有（100）个空指针域</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="二叉树与树，森林之间的转换"><a href="#二叉树与树，森林之间的转换" class="headerlink" title="二叉树与树，森林之间的转换"></a>二叉树与树，森林之间的转换</h3><ul>
<li><p>树转换为二叉树</p>
<ul>
<li>1、树中所有相邻兄弟之间加一条连线</li>
<li>2、对树中每个节点只保留跟第一个孩子之间的连线，删除与其他孩子之间的连线</li>
<li>3、以树的根节点为轴心，将整棵树顺时针旋转45度</li>
</ul>
</li>
<li><p>森林转换为二叉树</p>
<ul>
<li>1、将森林中的每棵树都转换成相应的二叉树</li>
<li>2、第一课二叉树不动，从第二颗二叉树开始，依次把后一颗二叉树的根结点作为前一颗二叉树根结点的右孩子结点。当所有二叉树连在一起后，此时得到的二叉树就是有森林转换得到的二叉树</li>
</ul>
</li>
<li><p>二叉树转换为树</p>
<ul>
<li>1、若某结点是其双亲结点的左孩子，则把该孩子的右孩子，右孩子的右孩子等都与该结点的双亲结点用连线连起来</li>
<li>2、删除原二叉树中所有双亲结点与右孩子结点之间的连线</li>
<li>3、整理由前面两步得到的树，即以根节点为轴心，逆时针旋转45度</li>
</ul>
</li>
<li><p>二叉树转换为森林</p>
</li>
</ul>
<h2 id="九：查找"><a href="#九：查找" class="headerlink" title="九：查找"></a>九：查找</h2><h3 id="平均查找长度"><a href="#平均查找长度" class="headerlink" title="平均查找长度"></a>平均查找长度</h3><ul>
<li>平均查找长度ASL的计算</li>
<li><p>总结</p>
<ul>
<li><p>二叉排序树的ASL</p>
<ul>
<li><p>成功</p>
<ul>
<li>（比较次数<em>不为空的结点数) </em> (比较次数*不为空的结点数）……/不为空的总结点数</li>
</ul>
</li>
<li><p>不成功</p>
<ul>
<li>到为空结点比较次数（不包括为空结点的比较次数，因为已经是空了，不需要在比较了）*为空的结点数/不为空的总结点数+1</li>
</ul>
</li>
</ul>
</li>
<li><p>哈希表的ASL</p>
<ul>
<li><p>成功</p>
<ul>
<li>所有探测次数相加/元素个数</li>
</ul>
</li>
<li><p>不成功</p>
<ul>
<li>什么时候才是不成功呢？待查关键字不在散列表中，要一直找到空元素才算查找失败。比如说一个不在哈希表中的关键字21，首先从第一个关键字14开始比较，直到找到空元素也就是散列地址为0的时候才算失败，这里探测次数是13次，然后关键字1开始，探测次数为12，……</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="静态查找表"><a href="#静态查找表" class="headerlink" title="静态查找表"></a>静态查找表</h3><ul>
<li>顺序表</li>
<li>有序表（折半查找）</li>
<li>静态树表（分块查找）</li>
<li>索引顺序表</li>
</ul>
<h3 id="顺序查找"><a href="#顺序查找" class="headerlink" title="顺序查找"></a>顺序查找</h3><ul>
<li>int Search(int a[], int n, int x)<br>{<br>  for (int i = n - 1; i &gt;= 0; i—)<br>  {<pre><code>  if (a[i] == x)return i;
</code></pre>  }<br>  return -1;<br>}</li>
</ul>
<h3 id="折半查找"><a href="#折半查找" class="headerlink" title="折半查找"></a>折半查找</h3><ul>
<li>int BinarySearch(int a[], int n,int x)<br>{<br>  int low = 0, high = n - 1;<br>  while (low &lt;= high)<br>  {<pre><code>  int mid = (low + high) / 2;
  if (a[mid] == x)return mid;
  else if (a[mid] &lt; x)low = mid+1;
  else high = mid-1;
</code></pre>  }<br>  return -1;<br>}</li>
</ul>
<h3 id="动态查找表"><a href="#动态查找表" class="headerlink" title="动态查找表"></a>动态查找表</h3><ul>
<li><p>二叉排序树</p>
<ul>
<li><p>概念</p>
<ul>
<li>若根结点的左子树非空，则左子树的所有结点关键字均小于根节点的关键字，</li>
<li>若根结点的右子树非空，则右子树的关键字的所有结点关键字均大于根节点的关键字</li>
<li>根结点的左右子树本身又各是一个二叉排序树</li>
</ul>
</li>
<li><p>实现：</p>
<ul>
<li>//二叉排序树查找关键字<br>BiTree Search_BST(BitTree T,DataType x)///二叉树查找关健字非递归版：<br>{<br>BiTree *p = T;<br>while (p)<br>{<br>if (p-&gt;data == x) return p;<br>p = (x &lt; p-&gt;data) ? p-&gt;lchild : p-&gt;rchild;<br>}<br>return NULL;<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>平衡二叉树（AVL树）</p>
<ul>
<li>一般情况下，一颗平衡二叉树总是二叉排序树，脱离二叉排序树来讨论平衡二叉树是没有意义的</li>
<li><p>一棵AVL树有如下必要条件：</p>
<ul>
<li>条件一：它必须是二叉查找树。</li>
<li>条件二：每个节点的左子树和右子树的高度差至多为1。</li>
</ul>
</li>
<li><p>AVL树的查找、插入、删除操作在平均和最坏的情况下都是O（logn）</p>
</li>
<li>平衡二叉树的构造</li>
</ul>
</li>
<li><p>B树</p>
</li>
<li>B+树</li>
</ul>
<h3 id="哈希表的查找"><a href="#哈希表的查找" class="headerlink" title="哈希表的查找"></a>哈希表的查找</h3><ul>
<li>哈希表（存放键值（地址）和数值的存储结构）</li>
<li>哈希函数（把数值映射（帮这个数值找一个地址）到地址的函数）</li>
<li><p>哈希函数的构造方法</p>
<ul>
<li><p>直接定址法</p>
<ul>
<li>直接以关键字（本身数值）或关键字加上某个常量作为地址</li>
<li><p>好处</p>
<ul>
<li>计算简单</li>
</ul>
</li>
<li><p>缺点</p>
<ul>
<li>关键字不连续的时候会造成内存浪费</li>
</ul>
</li>
</ul>
</li>
<li><p>除留余数法</p>
<ul>
<li>关键字除以一个整数p所得余数作为哈希地址</li>
</ul>
</li>
<li><p>数字分析法</p>
<ul>
<li>提取关键字中取值较均匀的数字作为哈希地址</li>
</ul>
</li>
</ul>
</li>
<li><p>必须解决的问题</p>
<ul>
<li>构造一个好的哈希函数，确定一个解决冲突的方法</li>
<li><p>哈希冲突的解决方法</p>
<ul>
<li>开放定址法</li>
<li><p>线性探测法</p>
<ul>
<li><p>缺点</p>
<ul>
<li>容易发生堆聚现象</li>
</ul>
</li>
</ul>
</li>
<li><p>平方探测法</p>
</li>
<li>拉链法（把产生冲突的位置放在一个单链表里）</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="子主题-3"><a href="#子主题-3" class="headerlink" title="子主题 3"></a>子主题 3</h2><h3 id="图"><a href="#图" class="headerlink" title="### 图"></a>### 图</h3><h3 id="图的定义"><a href="#图的定义" class="headerlink" title="- 图的定义"></a>- 图的定义</h3><h3 id="图G是由顶点集V-边集E组成"><a href="#图G是由顶点集V-边集E组成" class="headerlink" title="- 图G是由顶点集V 边集E组成"></a>- 图G是由顶点集V 边集E组成</h3><h3 id="有向图"><a href="#有向图" class="headerlink" title="- 有向图"></a>- 有向图</h3><h3 id="无向图"><a href="#无向图" class="headerlink" title="- 无向图"></a>- 无向图</h3><h3 id="简单图"><a href="#简单图" class="headerlink" title="- 简单图"></a>- 简单图</h3><h3 id="多重图"><a href="#多重图" class="headerlink" title="- 多重图"></a>- 多重图</h3><h3 id="完全图"><a href="#完全图" class="headerlink" title="- 完全图"></a>- 完全图</h3><h3 id="子图"><a href="#子图" class="headerlink" title="- 子图"></a>- 子图</h3><h3 id="连通"><a href="#连通" class="headerlink" title="- 连通"></a>- 连通</h3><h3 id="连通图"><a href="#连通图" class="headerlink" title="- 连通图"></a>- 连通图</h3><h3 id="连通分量"><a href="#连通分量" class="headerlink" title="- 连通分量"></a>- 连通分量</h3><h3 id="强连通图"><a href="#强连通图" class="headerlink" title="- 强连通图"></a>- 强连通图</h3><h3 id="子主题-1"><a href="#子主题-1" class="headerlink" title="- 子主题 1"></a>- 子主题 1</h3><h3 id="极大连通子图"><a href="#极大连通子图" class="headerlink" title="- 极大连通子图"></a>- 极大连通子图</h3><h3 id="极小连通子图"><a href="#极小连通子图" class="headerlink" title="- 极小连通子图"></a>- 极小连通子图</h3><h3 id="生成树"><a href="#生成树" class="headerlink" title="- 生成树"></a>- 生成树</h3><h3 id="n个顶点的、n-1条边"><a href="#n个顶点的、n-1条边" class="headerlink" title="- n个顶点的、n-1条边"></a>- n个顶点的、n-1条边</h3><h3 id="生成森林"><a href="#生成森林" class="headerlink" title="- 生成森林"></a>- 生成森林</h3><h3 id="非连通图所有连通分量的生成树组成的森林"><a href="#非连通图所有连通分量的生成树组成的森林" class="headerlink" title="- 非连通图所有连通分量的生成树组成的森林"></a>- 非连通图所有连通分量的生成树组成的森林</h3><h3 id="顶点的度"><a href="#顶点的度" class="headerlink" title="- 顶点的度"></a>- 顶点的度</h3><h3 id="以该顶点为一个端点的数目"><a href="#以该顶点为一个端点的数目" class="headerlink" title="- 以该顶点为一个端点的数目"></a>- 以该顶点为一个端点的数目</h3><h3 id="出度入度-有向图"><a href="#出度入度-有向图" class="headerlink" title="- 出度入度(有向图)"></a>- 出度入度(有向图)</h3><h3 id="TD-v"><a href="#TD-v" class="headerlink" title="- TD(v)"></a>- TD(v)</h3><h3 id="网"><a href="#网" class="headerlink" title="- 网"></a>- 网</h3><h3 id="稠密图"><a href="#稠密图" class="headerlink" title="- 稠密图"></a>- 稠密图</h3><h3 id="稀疏图"><a href="#稀疏图" class="headerlink" title="- 稀疏图"></a>- 稀疏图</h3><h3 id="有向树"><a href="#有向树" class="headerlink" title="- 有向树"></a>- 有向树</h3><h3 id="入度-为0"><a href="#入度-为0" class="headerlink" title="- 入度 为0"></a>- 入度 为0</h3><h3 id="其余-入度均为1"><a href="#其余-入度均为1" class="headerlink" title="- 其余 入度均为1"></a>- 其余 入度均为1</h3><h3 id="路径"><a href="#路径" class="headerlink" title="- 路径"></a>- 路径</h3><h3 id="简单lujing"><a href="#简单lujing" class="headerlink" title="- 简单lujing"></a>- 简单lujing</h3><h3 id="距离"><a href="#距离" class="headerlink" title="- 距离"></a>- 距离</h3><h3 id="图的存储结构"><a href="#图的存储结构" class="headerlink" title="- 图的存储结构"></a>- 图的存储结构</h3><h3 id="邻接矩阵法"><a href="#邻接矩阵法" class="headerlink" title="- 邻接矩阵法"></a>- 邻接矩阵法</h3><h3 id="性质"><a href="#性质" class="headerlink" title="- 性质"></a>- 性质</h3><h3 id="空间复杂度-O-n-2"><a href="#空间复杂度-O-n-2" class="headerlink" title="- 空间复杂度 O(n^2)"></a>- 空间复杂度 O(n^2)</h3><h3 id="时间复杂度-O-n-2"><a href="#时间复杂度-O-n-2" class="headerlink" title="- 时间复杂度 O(n^2)"></a>- 时间复杂度 O(n^2)</h3><h3 id="无向图的是对称矩阵"><a href="#无向图的是对称矩阵" class="headerlink" title="- 无向图的是对称矩阵"></a>- 无向图的是对称矩阵</h3><h3 id="A-n的含义："><a href="#A-n的含义：" class="headerlink" title="- A^n的含义："></a>- A^n的含义：</h3><h3 id="邻接表法"><a href="#邻接表法" class="headerlink" title="- 邻接表法"></a>- 邻接表法</h3><h3 id="有向图-1"><a href="#有向图-1" class="headerlink" title="- 有向图"></a>- 有向图</h3><h3 id="出度"><a href="#出度" class="headerlink" title="- 出度"></a>- 出度</h3><h3 id="遍历顶点表节点所对应的边表"><a href="#遍历顶点表节点所对应的边表" class="headerlink" title="- 遍历顶点表节点所对应的边表"></a>- 遍历顶点表节点所对应的边表</h3><h3 id="入度"><a href="#入度" class="headerlink" title="- 入度"></a>- 入度</h3><h3 id="遍历剩下所有结点"><a href="#遍历剩下所有结点" class="headerlink" title="- 遍历剩下所有结点"></a>- 遍历剩下所有结点</h3><h3 id="无向图-1"><a href="#无向图-1" class="headerlink" title="- 无向图"></a>- 无向图</h3><h3 id="第i个顶点的度时第i个链表中的节点数"><a href="#第i个顶点的度时第i个链表中的节点数" class="headerlink" title="- 第i个顶点的度时第i个链表中的节点数"></a>- 第i个顶点的度时第i个链表中的节点数</h3><h3 id="时间复杂度-O-n-e"><a href="#时间复杂度-O-n-e" class="headerlink" title="- 时间复杂度 O(n+e)"></a>- 时间复杂度 O(n+e)</h3><h3 id="临界多重表"><a href="#临界多重表" class="headerlink" title="- 临界多重表"></a>- 临界多重表</h3><h3 id="无向图-2"><a href="#无向图-2" class="headerlink" title="- 无向图"></a>- 无向图</h3><h3 id="十字链表"><a href="#十字链表" class="headerlink" title="- 十字链表"></a>- 十字链表</h3><h3 id="有向图-2"><a href="#有向图-2" class="headerlink" title="- 有向图"></a>- 有向图</h3><h3 id="矩阵压缩"><a href="#矩阵压缩" class="headerlink" title="- 矩阵压缩"></a>- 矩阵压缩</h3><h3 id="下标"><a href="#下标" class="headerlink" title="- 下标"></a>- 下标</h3><h3 id="对称矩阵"><a href="#对称矩阵" class="headerlink" title="- 对称矩阵"></a>- 对称矩阵</h3><h3 id="n-n-1-2"><a href="#n-n-1-2" class="headerlink" title="- n(n+1)/2"></a>- n(n+1)/2</h3><h3 id="三对角阵"><a href="#三对角阵" class="headerlink" title="- 三对角阵"></a>- 三对角阵</h3><h3 id="k-2i-j-3"><a href="#k-2i-j-3" class="headerlink" title="- k=2i+j-3"></a>- k=2i+j-3</h3><h3 id="树的路径长度"><a href="#树的路径长度" class="headerlink" title="- 树的路径长度"></a>- 树的路径长度</h3><h3 id="所有路径的总和"><a href="#所有路径的总和" class="headerlink" title="- 所有路径的总和"></a>- 所有路径的总和</h3><h3 id="哈夫曼的带权路径"><a href="#哈夫曼的带权路径" class="headerlink" title="- 哈夫曼的带权路径"></a>- 哈夫曼的带权路径</h3><h3 id="图的基本操作"><a href="#图的基本操作" class="headerlink" title="- 图的基本操作"></a>- 图的基本操作</h3><h3 id="图G是否存在边"><a href="#图G是否存在边" class="headerlink" title="- 图G是否存在边"></a>- 图G是否存在边</h3><h3 id="adjacent-G-x-y"><a href="#adjacent-G-x-y" class="headerlink" title="- adjacent(G,x,y)"></a>- adjacent(G,x,y)</h3><h3 id="列出图G中与x临界的边"><a href="#列出图G中与x临界的边" class="headerlink" title="- 列出图G中与x临界的边"></a>- 列出图G中与x临界的边</h3><h3 id="Neighbors-G-x"><a href="#Neighbors-G-x" class="headerlink" title="- Neighbors(G.x)"></a>- Neighbors(G.x)</h3><h3 id="插入定点x"><a href="#插入定点x" class="headerlink" title="- 插入定点x"></a>- 插入定点x</h3><h3 id="删除顶点x"><a href="#删除顶点x" class="headerlink" title="- 删除顶点x"></a>- 删除顶点x</h3><h3 id="若边不存在，则添加边"><a href="#若边不存在，则添加边" class="headerlink" title="- 若边不存在，则添加边"></a>- 若边不存在，则添加边</h3><h3 id="若边存在，删除边"><a href="#若边存在，删除边" class="headerlink" title="- 若边存在，删除边"></a>- 若边存在，删除边</h3><h3 id="求顶点x的第一个邻接点"><a href="#求顶点x的第一个邻接点" class="headerlink" title="- 求顶点x的第一个邻接点"></a>- 求顶点x的第一个邻接点</h3><h3 id="获取边的权值"><a href="#获取边的权值" class="headerlink" title="- 获取边的权值"></a>- 获取边的权值</h3><h3 id="设置边的权值"><a href="#设置边的权值" class="headerlink" title="- 设置边的权值"></a>- 设置边的权值</h3><h3 id="图的遍历-1"><a href="#图的遍历-1" class="headerlink" title="- 图的遍历"></a>- 图的遍历</h3><h3 id="广度优先遍历"><a href="#广度优先遍历" class="headerlink" title="- 广度优先遍历"></a>- 广度优先遍历</h3><h3 id="从某个顶点开始，访问所有顶点访问一次"><a href="#从某个顶点开始，访问所有顶点访问一次" class="headerlink" title="- 从某个顶点开始，访问所有顶点访问一次"></a>- 从某个顶点开始，访问所有顶点访问一次</h3><h3 id="首先访问起始顶点v"><a href="#首先访问起始顶点v" class="headerlink" title="- 首先访问起始顶点v"></a>- 首先访问起始顶点v</h3><h3 id="接着由出发依次访问v的各个未被访问的节点"><a href="#接着由出发依次访问v的各个未被访问的节点" class="headerlink" title="- 接着由出发依次访问v的各个未被访问的节点"></a>- 接着由出发依次访问v的各个未被访问的节点</h3><h3 id="然后依次访问w的所有未被访问的节点"><a href="#然后依次访问w的所有未被访问的节点" class="headerlink" title="- 然后依次访问w的所有未被访问的节点"></a>- 然后依次访问w的所有未被访问的节点</h3><h3 id="子主题-5-1"><a href="#子主题-5-1" class="headerlink" title="- 子主题 5"></a>- 子主题 5</h3><h3 id="队列-辅助标记数组"><a href="#队列-辅助标记数组" class="headerlink" title="- 队列+辅助标记数组"></a>- 队列+辅助标记数组</h3><h3 id="BFS算法"><a href="#BFS算法" class="headerlink" title="- BFS算法"></a>- BFS算法</h3><h3 id="空间复杂度"><a href="#空间复杂度" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="O-V"><a href="#O-V" class="headerlink" title="- O(|V|)"></a>- O(|V|)</h3><h3 id="时间复杂度"><a href="#时间复杂度" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="邻接矩阵法-1"><a href="#邻接矩阵法-1" class="headerlink" title="- 邻接矩阵法"></a>- 邻接矩阵法</h3><h3 id="O-V-2"><a href="#O-V-2" class="headerlink" title="- O(|V^2|)"></a>- O(|V^2|)</h3><h3 id="邻接表法-1"><a href="#邻接表法-1" class="headerlink" title="- 邻接表法"></a>- 邻接表法</h3><h3 id="O-V-E"><a href="#O-V-E" class="headerlink" title="- O(|V+E|)"></a>- O(|V+E|)</h3><h3 id="无权图单源最短路径问题"><a href="#无权图单源最短路径问题" class="headerlink" title="- 无权图单源最短路径问题"></a>- 无权图单源最短路径问题</h3><h3 id="图的广度优先遍历"><a href="#图的广度优先遍历" class="headerlink" title="- 图的广度优先遍历"></a>- 图的广度优先遍历</h3><h3 id="void-BFSTraverse-Graph-G"><a href="#void-BFSTraverse-Graph-G" class="headerlink" title="- void BFSTraverse(Graph G)"></a>- void BFSTraverse(Graph G)</h3><h3 id=""><a href="#" class="headerlink" title="{"></a>{</h3><h3 id="visited-0-G-vexnum-1-false-初始化访问标记为未访问"><a href="#visited-0-G-vexnum-1-false-初始化访问标记为未访问" class="headerlink" title="visited[0 ..G.vexnum - 1] = false;//初始化访问标记为未访问"></a>visited[0 ..G.vexnum - 1] = false;//初始化访问标记为未访问</h3><h3 id="InitQueue-Q"><a href="#InitQueue-Q" class="headerlink" title="InitQueue(Q);"></a>InitQueue(Q);</h3><h3 id="for-v-0-v-lt-G-vexnum-v"><a href="#for-v-0-v-lt-G-vexnum-v" class="headerlink" title="for (v = 0; v &lt; G.vexnum; v++)"></a>for (v = 0; v &lt; G.vexnum; v++)</h3><h3 id="if-visited-v"><a href="#if-visited-v" class="headerlink" title="if (!visited[v])"></a>if (!visited[v])</h3><h3 id="-1"><a href="#-1" class="headerlink" title="{"></a>{</h3><h3 id="visit-v"><a href="#visit-v" class="headerlink" title="visit(v);"></a>visit(v);</h3><h3 id="visited-v-true"><a href="#visited-v-true" class="headerlink" title="visited[v] = true;"></a>visited[v] = true;</h3><h3 id="EnQueue-Q-v"><a href="#EnQueue-Q-v" class="headerlink" title="EnQueue(Q, v);"></a>EnQueue(Q, v);</h3><h3 id="while"><a href="#while" class="headerlink" title="while(!)"></a>while(!)</h3><h3 id="DFS-G-v-从未被访问的顶点开始"><a href="#DFS-G-v-从未被访问的顶点开始" class="headerlink" title="DFS(G.v);//从未被访问的顶点开始"></a>DFS(G.v);//从未被访问的顶点开始</h3><h3 id="-2"><a href="#-2" class="headerlink" title="}"></a>}</h3><h3 id="-3"><a href="#-3" class="headerlink" title="}"></a>}</h3><h3 id="void-BFS-Graph-G-int-v"><a href="#void-BFS-Graph-G-int-v" class="headerlink" title="void BFS(Graph G, int v)"></a>void BFS(Graph G, int v)</h3><h3 id="-4"><a href="#-4" class="headerlink" title="{"></a>{</h3><h3 id="visit-v-访问顶点v"><a href="#visit-v-访问顶点v" class="headerlink" title="visit(v);//访问顶点v"></a>visit(v);//访问顶点v</h3><h3 id="visited-v-true-1"><a href="#visited-v-true-1" class="headerlink" title="visited[v] = true;"></a>visited[v] = true;</h3><h3 id="for-w-FistAdjVec-G-v-w-gt-0-w-NextAdjVex-G-v-w"><a href="#for-w-FistAdjVec-G-v-w-gt-0-w-NextAdjVex-G-v-w" class="headerlink" title="for (w = FistAdjVec(G.v); w &gt;= 0; w = NextAdjVex(G, v, w))"></a>for (w = FistAdjVec(G.v); w &gt;= 0; w = NextAdjVex(G, v, w))</h3><h3 id="if-visited-w-DFS-G-w"><a href="#if-visited-w-DFS-G-w" class="headerlink" title="if (!visited[w])DFS(G, w);"></a>if (!visited[w])DFS(G, w);</h3><h3 id="-5"><a href="#-5" class="headerlink" title="}"></a>}</h3><ul>
<li><ul>
<li>深度优先遍历</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>图的深度优先遍历</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><ul>
<li>void DFSTraverse(Graph G)</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="-6"><a href="#-6" class="headerlink" title="{"></a>{</h3><ul>
<li>visited[0 ..G.vexnum - 1] = false;//初始化访问标记为未访问</li>
<li><p>for (v = 0; v &lt; G.vexnum; v++)</p>
<ul>
<li>if (!visited[v])DFS(G.v);//从未被访问的顶点开始</li>
</ul>
</li>
</ul>
<h3 id="-7"><a href="#-7" class="headerlink" title="}"></a>}</h3><h3 id="void-DFS-Graph-G-int-v"><a href="#void-DFS-Graph-G-int-v" class="headerlink" title="void DFS(Graph G, int v)"></a>void DFS(Graph G, int v)</h3><h3 id="-8"><a href="#-8" class="headerlink" title="{"></a>{</h3><ul>
<li>visit(v);//访问顶点v</li>
<li>visited[v] = true;</li>
<li><p>for (w = FistAdjVec(G.v); w &gt;= 0; w = NextAdjVex(G, v, w))</p>
<ul>
<li>if (!visited[w])DFS(G,w);</li>
</ul>
</li>
</ul>
<h3 id="-9"><a href="#-9" class="headerlink" title="}"></a>}</h3><h3 id="图的应用-1"><a href="#图的应用-1" class="headerlink" title="- 图的应用"></a>- 图的应用</h3><h3 id="最小生成树"><a href="#最小生成树" class="headerlink" title="- 最小生成树"></a>- 最小生成树</h3><h3 id="prim"><a href="#prim" class="headerlink" title="- prim"></a>- prim</h3><h3 id="对比"><a href="#对比" class="headerlink" title="- 对比"></a>- 对比</h3><h3 id="O-N-2"><a href="#O-N-2" class="headerlink" title="- O(N^2)"></a>- O(N^2)</h3><h3 id="时间复杂度-1"><a href="#时间复杂度-1" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="只与顶点个数有关"><a href="#只与顶点个数有关" class="headerlink" title="- 只与顶点个数有关"></a>- 只与顶点个数有关</h3><h3 id="适用于稠密图"><a href="#适用于稠密图" class="headerlink" title="- 适用于稠密图"></a>- 适用于稠密图</h3><h3 id="特点"><a href="#特点" class="headerlink" title="- 特点"></a>- 特点</h3><h3 id="只与边的个数有关"><a href="#只与边的个数有关" class="headerlink" title="- 只与边的个数有关"></a>- 只与边的个数有关</h3><h3 id="适用于稀疏图"><a href="#适用于稀疏图" class="headerlink" title="- 适用于稀疏图"></a>- 适用于稀疏图</h3><h3 id="O-eloge"><a href="#O-eloge" class="headerlink" title="- O(eloge)"></a>- O(eloge)</h3><h3 id="kruskal"><a href="#kruskal" class="headerlink" title="- kruskal"></a>- kruskal</h3><h3 id="最短路径"><a href="#最短路径" class="headerlink" title="- 最短路径"></a>- 最短路径</h3><h3 id="dijkstra"><a href="#dijkstra" class="headerlink" title="- dijkstra"></a>- dijkstra</h3><h3 id="floyd"><a href="#floyd" class="headerlink" title="- floyd"></a>- floyd</h3><h3 id="有向无环图"><a href="#有向无环图" class="headerlink" title="- 有向无环图"></a>- 有向无环图</h3><h3 id="DAG图"><a href="#DAG图" class="headerlink" title="- DAG图"></a>- DAG图</h3><h3 id="AOV网"><a href="#AOV网" class="headerlink" title="- AOV网"></a>- AOV网</h3><h3 id="每个顶点出现有且只有一次"><a href="#每个顶点出现有且只有一次" class="headerlink" title="- 每个顶点出现有且只有一次"></a>- 每个顶点出现有且只有一次</h3><h3 id="A在序列B前面，则图中不存在B到A的路径"><a href="#A在序列B前面，则图中不存在B到A的路径" class="headerlink" title="- A在序列B前面，则图中不存在B到A的路径"></a>- A在序列B前面，则图中不存在B到A的路径</h3><h3 id="关键路径"><a href="#关键路径" class="headerlink" title="- 关键路径"></a>- 关键路径</h3><h3 id="AOE网"><a href="#AOE网" class="headerlink" title="- AOE网"></a>- AOE网</h3><h3 id="事件i"><a href="#事件i" class="headerlink" title="- 事件i"></a>- 事件i</h3><h3 id="最早发生时间"><a href="#最早发生时间" class="headerlink" title="- 最早发生时间"></a>- 最早发生时间</h3><h3 id="ve-i"><a href="#ve-i" class="headerlink" title="- ve(i)"></a>- ve(i)</h3><h3 id="最晚发生时间"><a href="#最晚发生时间" class="headerlink" title="- 最晚发生时间"></a>- 最晚发生时间</h3><h3 id="vl-i"><a href="#vl-i" class="headerlink" title="- vl(i)"></a>- vl(i)</h3><h3 id="活动最早开始时间"><a href="#活动最早开始时间" class="headerlink" title="- 活动最早开始时间"></a>- 活动最早开始时间</h3><h3 id="e-i-j"><a href="#e-i-j" class="headerlink" title="- e(i,j)"></a>- e(i,j)</h3><h3 id="工程需要多长时间"><a href="#工程需要多长时间" class="headerlink" title="- 工程需要多长时间"></a>- 工程需要多长时间</h3><h3 id="关键路径的计算"><a href="#关键路径的计算" class="headerlink" title="- 关键路径的计算"></a>- 关键路径的计算</h3><h3 id="按拓扑有序排序顶点"><a href="#按拓扑有序排序顶点" class="headerlink" title="- 按拓扑有序排序顶点"></a>- 按拓扑有序排序顶点</h3><h3 id="计算Ve-j"><a href="#计算Ve-j" class="headerlink" title="- 计算Ve(j)"></a>- 计算Ve(j)</h3><h3 id="ve-1-0"><a href="#ve-1-0" class="headerlink" title="- ve(1)=0"></a>- ve(1)=0</h3><h3 id="ve-j-max-ve-a-j"><a href="#ve-j-max-ve-a-j" class="headerlink" title="- ve(j)=max{ve()+a(,j)}"></a>- ve(j)=max{ve(<em>)+a(</em>,j)}</h3><h3 id="是任意前驱"><a href="#是任意前驱" class="headerlink" title="- *是任意前驱"></a>- *是任意前驱</h3><h3 id="计算vl-i"><a href="#计算vl-i" class="headerlink" title="- 计算vl(i)"></a>- 计算vl(i)</h3><h3 id="vl-n-ve-n"><a href="#vl-n-ve-n" class="headerlink" title="- vl(n)=ve(n)"></a>- vl(n)=ve(n)</h3><h3 id="vl-i-min-vl-a-i"><a href="#vl-i-min-vl-a-i" class="headerlink" title="- vl(i)=min{vl()-a(i,)}"></a>- vl(i)=min{vl(<em>)-a(i,</em>)}</h3><h3 id="求e-i-j-l-i-j"><a href="#求e-i-j-l-i-j" class="headerlink" title="- 求e(i,j)  l(i,j)"></a>- 求e(i,j)  l(i,j)</h3><h3 id="e-i-j-ve-i"><a href="#e-i-j-ve-i" class="headerlink" title="- e(i,j)=ve(i)"></a>- e(i,j)=ve(i)</h3><h3 id="l-i-j-vl-j-a-i-j"><a href="#l-i-j-vl-j-a-i-j" class="headerlink" title="- l(i,j)=vl(j)-a(i,j)"></a>- l(i,j)=vl(j)-a(i,j)</h3><h3 id="工程总用时：ve-n"><a href="#工程总用时：ve-n" class="headerlink" title="- 工程总用时：ve(n)"></a>- 工程总用时：ve(n)</h3><h3 id="关键活动-e-i-j-l-i-j"><a href="#关键活动-e-i-j-l-i-j" class="headerlink" title="- 关键活动  e(i,j)=l(i,j)"></a>- 关键活动  e(i,j)=l(i,j)</h3><h3 id="第六章-查找"><a href="#第六章-查找" class="headerlink" title="### 第六章  查找"></a>### 第六章  查找</h3><h3 id="概念"><a href="#概念" class="headerlink" title="- 概念"></a>- 概念</h3><h3 id="查找"><a href="#查找" class="headerlink" title="- 查找"></a>- 查找</h3><h3 id="根据给定的值，查找表中确定一个其关键字等于给定值的记录或者数据元素"><a href="#根据给定的值，查找表中确定一个其关键字等于给定值的记录或者数据元素" class="headerlink" title="- 根据给定的值，查找表中确定一个其关键字等于给定值的记录或者数据元素"></a>- 根据给定的值，查找表中确定一个其关键字等于给定值的记录或者数据元素</h3><h3 id="查找表"><a href="#查找表" class="headerlink" title="- 查找表"></a>- 查找表</h3><h3 id="是由同一类型的数据元素构成的集合"><a href="#是由同一类型的数据元素构成的集合" class="headerlink" title="- 是由同一类型的数据元素构成的集合"></a>- 是由同一类型的数据元素构成的集合</h3><h3 id="松散"><a href="#松散" class="headerlink" title="- 松散"></a>- 松散</h3><h3 id="静态查找"><a href="#静态查找" class="headerlink" title="- 静态查找"></a>- 静态查找</h3><h3 id="只做查询数据和属性的操作"><a href="#只做查询数据和属性的操作" class="headerlink" title="- 只做查询数据和属性的操作"></a>- 只做查询数据和属性的操作</h3><h3 id="顺序查找表"><a href="#顺序查找表" class="headerlink" title="- 顺序查找表"></a>- 顺序查找表</h3><h3 id="思路简单，适用面广"><a href="#思路简单，适用面广" class="headerlink" title="- 思路简单，适用面广"></a>- 思路简单，适用面广</h3><h3 id="平均查找长度-1"><a href="#平均查找长度-1" class="headerlink" title="- 平均查找长度"></a>- 平均查找长度</h3><h3 id="ASL-1-2-3-……-n-n-n-1-2"><a href="#ASL-1-2-3-……-n-n-n-1-2" class="headerlink" title="- ASL=(1+2+3+……+n)/n=(n+1)/2"></a>- ASL=(1+2+3+……+n)/n=(n+1)/2</h3><h3 id="时间复杂度-2"><a href="#时间复杂度-2" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O-n"><a href="#O-n" class="headerlink" title="- O(n)"></a>- O(n)</h3><h3 id="顺序查找-1"><a href="#顺序查找-1" class="headerlink" title="- 顺序查找"></a>- 顺序查找</h3><h3 id="int-Search-int-a-int-n-int-x"><a href="#int-Search-int-a-int-n-int-x" class="headerlink" title="- int Search(int a[], int n, int x)"></a>- int Search(int a[], int n, int x)</h3><h3 id="-10"><a href="#-10" class="headerlink" title="{"></a>{</h3><h3 id="for-int-i-n-1-i-gt-0-i—"><a href="#for-int-i-n-1-i-gt-0-i—" class="headerlink" title="for (int i = n - 1; i &gt;= 0; i—)"></a>for (int i = n - 1; i &gt;= 0; i—)</h3><h3 id="-11"><a href="#-11" class="headerlink" title="{"></a>{</h3><h3 id="if-a-i-x-return-i"><a href="#if-a-i-x-return-i" class="headerlink" title="if (a[i] == x)return i;"></a>if (a[i] == x)return i;</h3><h3 id="-12"><a href="#-12" class="headerlink" title="}"></a>}</h3><h3 id="return-1"><a href="#return-1" class="headerlink" title="return -1;"></a>return -1;</h3><h3 id="-13"><a href="#-13" class="headerlink" title="}"></a>}</h3><h3 id="折半查找表"><a href="#折半查找表" class="headerlink" title="- 折半查找表"></a>- 折半查找表</h3><h3 id="速度快，要去查找表有序，且随机访问"><a href="#速度快，要去查找表有序，且随机访问" class="headerlink" title="- 速度快，要去查找表有序，且随机访问"></a>- 速度快，要去查找表有序，且随机访问</h3><h3 id="平均查找长度-2"><a href="#平均查找长度-2" class="headerlink" title="- 平均查找长度"></a>- 平均查找长度</h3><h3 id="ASL-log-n-1-1"><a href="#ASL-log-n-1-1" class="headerlink" title="- ASL=log(n+1)-1"></a>- ASL=log(n+1)-1</h3><h3 id="时间复杂度-3"><a href="#时间复杂度-3" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O-logn"><a href="#O-logn" class="headerlink" title="- O(logn)"></a>- O(logn)</h3><h3 id="折半查找-1"><a href="#折半查找-1" class="headerlink" title="- 折半查找"></a>- 折半查找</h3><h3 id="int-BinarySearch-int-a-int-n-int-x"><a href="#int-BinarySearch-int-a-int-n-int-x" class="headerlink" title="- int BinarySearch(int a[], int n,int x)"></a>- int BinarySearch(int a[], int n,int x)</h3><h3 id="-14"><a href="#-14" class="headerlink" title="{"></a>{</h3><h3 id="int-low-0-high-n-1"><a href="#int-low-0-high-n-1" class="headerlink" title="int low = 0, high = n - 1;"></a>int low = 0, high = n - 1;</h3><h3 id="while-low-lt-high"><a href="#while-low-lt-high" class="headerlink" title="while (low &lt;= high)"></a>while (low &lt;= high)</h3><h3 id="-15"><a href="#-15" class="headerlink" title="{"></a>{</h3><h3 id="int-mid-low-high-2"><a href="#int-mid-low-high-2" class="headerlink" title="int mid = (low + high) / 2;"></a>int mid = (low + high) / 2;</h3><h3 id="if-a-mid-x-return-mid"><a href="#if-a-mid-x-return-mid" class="headerlink" title="if (a[mid] == x)return mid;"></a>if (a[mid] == x)return mid;</h3><h3 id="else-if-a-mid-lt-x-low-mid-1"><a href="#else-if-a-mid-lt-x-low-mid-1" class="headerlink" title="else if (a[mid] &lt; x)low = mid+1;"></a>else if (a[mid] &lt; x)low = mid+1;</h3><h3 id="else-high-mid-1"><a href="#else-high-mid-1" class="headerlink" title="else high = mid-1;"></a>else high = mid-1;</h3><h3 id="-16"><a href="#-16" class="headerlink" title="}"></a>}</h3><h3 id="return-1-1"><a href="#return-1-1" class="headerlink" title="return -1;"></a>return -1;</h3><h3 id="-17"><a href="#-17" class="headerlink" title="}"></a>}</h3><h3 id="静态树表"><a href="#静态树表" class="headerlink" title="- 静态树表"></a>- 静态树表</h3><h3 id="次优查找表"><a href="#次优查找表" class="headerlink" title="- 次优查找表"></a>- 次优查找表</h3><h3 id="索引查找表"><a href="#索引查找表" class="headerlink" title="- 索引查找表"></a>- 索引查找表</h3><h3 id="动态查找"><a href="#动态查找" class="headerlink" title="- 动态查找"></a>- 动态查找</h3><h3 id="查找过程中同时插入表中不存在的数据元素"><a href="#查找过程中同时插入表中不存在的数据元素" class="headerlink" title="- 查找过程中同时插入表中不存在的数据元素"></a>- 查找过程中同时插入表中不存在的数据元素</h3><h3 id="从查找表中删除已存在的元素"><a href="#从查找表中删除已存在的元素" class="headerlink" title="- 从查找表中删除已存在的元素"></a>- 从查找表中删除已存在的元素</h3><h3 id="二叉排序树"><a href="#二叉排序树" class="headerlink" title="- 二叉排序树"></a>- 二叉排序树</h3><h3 id="平衡二叉树"><a href="#平衡二叉树" class="headerlink" title="- 平衡二叉树"></a>- 平衡二叉树</h3><h3 id="B-树"><a href="#B-树" class="headerlink" title="- B-树"></a>- B-树</h3><h3 id="m阶B-树"><a href="#m阶B-树" class="headerlink" title="- m阶B-树"></a>- m阶B-树</h3><h3 id="空树"><a href="#空树" class="headerlink" title="- 空树"></a>- 空树</h3><h3 id="满足"><a href="#满足" class="headerlink" title="- 满足"></a>- 满足</h3><h3 id="每个节点至多有m棵子树"><a href="#每个节点至多有m棵子树" class="headerlink" title="- 每个节点至多有m棵子树"></a>- 每个节点至多有m棵子树</h3><h3 id="若根节点不是叶子，则至少有2棵子树"><a href="#若根节点不是叶子，则至少有2棵子树" class="headerlink" title="- 若根节点不是叶子，则至少有2棵子树"></a>- 若根节点不是叶子，则至少有2棵子树</h3><h3 id="除根结点的所有非终端结点至少有m-2棵子树-向上取整"><a href="#除根结点的所有非终端结点至少有m-2棵子树-向上取整" class="headerlink" title="- 除根结点的所有非终端结点至少有m/2棵子树(向上取整)"></a>- 除根结点的所有非终端结点至少有m/2棵子树(向上取整)</h3><h3 id="所有非终端结点包含n个关键字和m-1棵子树"><a href="#所有非终端结点包含n个关键字和m-1棵子树" class="headerlink" title="- 所有非终端结点包含n个关键字和m+1棵子树"></a>- 所有非终端结点包含n个关键字和m+1棵子树</h3><h3 id="n-A0-K1-A1-……，Kn-An"><a href="#n-A0-K1-A1-……，Kn-An" class="headerlink" title="- (n,A0,K1,A1,……，Kn,An)"></a>- (n,A0,K1,A1,……，Kn,An)</h3><h3 id="所有叶子结点在同一层，不含信息，表示查找失败"><a href="#所有叶子结点在同一层，不含信息，表示查找失败" class="headerlink" title="- 所有叶子结点在同一层，不含信息，表示查找失败"></a>- 所有叶子结点在同一层，不含信息，表示查找失败</h3><h3 id="B-树-1"><a href="#B-树-1" class="headerlink" title="- B+树"></a>- B+树</h3><h3 id="n棵子树包含n个关键字"><a href="#n棵子树包含n个关键字" class="headerlink" title="- n棵子树包含n个关键字"></a>- n棵子树包含n个关键字</h3><h3 id="顺序查找-随机查找"><a href="#顺序查找-随机查找" class="headerlink" title="- 顺序查找/随机查找"></a>- 顺序查找/随机查找</h3><h3 id="键树"><a href="#键树" class="headerlink" title="- 键树"></a>- 键树</h3><h3 id="哈希表"><a href="#哈希表" class="headerlink" title="- 哈希表"></a>- 哈希表</h3><h3 id="概念-1"><a href="#概念-1" class="headerlink" title="- 概念"></a>- 概念</h3><h3 id="散列表"><a href="#散列表" class="headerlink" title="- 散列表"></a>- 散列表</h3><h3 id="根据设定的散列函数和处理冲突的办法，将一组关键字映射到一个有限的地址集上，并以关键字在地质集中的像作为记录在表中的存储位置"><a href="#根据设定的散列函数和处理冲突的办法，将一组关键字映射到一个有限的地址集上，并以关键字在地质集中的像作为记录在表中的存储位置" class="headerlink" title="- 根据设定的散列函数和处理冲突的办法，将一组关键字映射到一个有限的地址集上，并以关键字在地质集中的像作为记录在表中的存储位置"></a>- 根据设定的散列函数和处理冲突的办法，将一组关键字映射到一个有限的地址集上，并以关键字在地质集中的像作为记录在表中的存储位置</h3><h3 id="关键字-存储地址的直接映射"><a href="#关键字-存储地址的直接映射" class="headerlink" title="- 关键字+存储地址的直接映射"></a>- 关键字+存储地址的直接映射</h3><h3 id="散列函数"><a href="#散列函数" class="headerlink" title="- 散列函数"></a>- 散列函数</h3><h3 id="把关键字映射成该关键字对应的地址的函数"><a href="#把关键字映射成该关键字对应的地址的函数" class="headerlink" title="- 把关键字映射成该关键字对应的地址的函数"></a>- 把关键字映射成该关键字对应的地址的函数</h3><h3 id="Hash-key-Addr"><a href="#Hash-key-Addr" class="headerlink" title="- Hash(key)=Addr"></a>- Hash(key)=Addr</h3><h3 id="冲突"><a href="#冲突" class="headerlink" title="- 冲突"></a>- 冲突</h3><h3 id="散列函数可能会把多个关键字映射到同一地址"><a href="#散列函数可能会把多个关键字映射到同一地址" class="headerlink" title="- 散列函数可能会把多个关键字映射到同一地址"></a>- 散列函数可能会把多个关键字映射到同一地址</h3><h3 id="装载因子"><a href="#装载因子" class="headerlink" title="- 装载因子"></a>- 装载因子</h3><h3 id="a-记录-地址空间"><a href="#a-记录-地址空间" class="headerlink" title="- a=记录/地址空间"></a>- a=记录/地址空间</h3><h3 id="处理冲突的方法"><a href="#处理冲突的方法" class="headerlink" title="- 处理冲突的方法"></a>- 处理冲突的方法</h3><h3 id="开放定址法"><a href="#开放定址法" class="headerlink" title="- 开放定址法"></a>- 开放定址法</h3><h3 id="线性探测再散列"><a href="#线性探测再散列" class="headerlink" title="- 线性探测再散列"></a>- 线性探测再散列</h3><h3 id="二次探测再散列"><a href="#二次探测再散列" class="headerlink" title="- 二次探测再散列"></a>- 二次探测再散列</h3><h3 id="伪随机探测再散列"><a href="#伪随机探测再散列" class="headerlink" title="- 伪随机探测再散列"></a>- 伪随机探测再散列</h3><h3 id="再哈希法"><a href="#再哈希法" class="headerlink" title="- 再哈希法"></a>- 再哈希法</h3><h3 id="更换散列函数"><a href="#更换散列函数" class="headerlink" title="- 更换散列函数"></a>- 更换散列函数</h3><h3 id="链地址法"><a href="#链地址法" class="headerlink" title="- 链地址法"></a>- 链地址法</h3><h3 id="发生冲突的改成单链表"><a href="#发生冲突的改成单链表" class="headerlink" title="- 发生冲突的改成单链表"></a>- 发生冲突的改成单链表</h3><h3 id="建立公共溢出区"><a href="#建立公共溢出区" class="headerlink" title="- 建立公共溢出区"></a>- 建立公共溢出区</h3><h3 id="所有的冲突记录存入溢出区"><a href="#所有的冲突记录存入溢出区" class="headerlink" title="- 所有的冲突记录存入溢出区"></a>- 所有的冲突记录存入溢出区</h3><h3 id="关键字"><a href="#关键字" class="headerlink" title="- 关键字"></a>- 关键字</h3><h3 id="数据元素中数据项的值"><a href="#数据元素中数据项的值" class="headerlink" title="- 数据元素中数据项的值"></a>- 数据元素中数据项的值</h3><h3 id="平均查找长度-3"><a href="#平均查找长度-3" class="headerlink" title="- 平均查找长度"></a>- 平均查找长度</h3><h3 id="ASL-PiCi"><a href="#ASL-PiCi" class="headerlink" title="- ASL=PiCi"></a>- ASL=PiCi</h3><h3 id="操作"><a href="#操作" class="headerlink" title="- 操作"></a>- 操作</h3><h3 id="查询特定数据元素是否在表中"><a href="#查询特定数据元素是否在表中" class="headerlink" title="- 查询特定数据元素是否在表中"></a>- 查询特定数据元素是否在表中</h3><h3 id="检索满足条件的数据元素的属性"><a href="#检索满足条件的数据元素的属性" class="headerlink" title="- 检索满足条件的数据元素的属性"></a>- 检索满足条件的数据元素的属性</h3><h3 id="查找表中插入元素"><a href="#查找表中插入元素" class="headerlink" title="- 查找表中插入元素"></a>- 查找表中插入元素</h3><h3 id="查找表删除元素"><a href="#查找表删除元素" class="headerlink" title="- 查找表删除元素"></a>- 查找表删除元素</h3><h3 id="线性结构"><a href="#线性结构" class="headerlink" title="- 线性结构"></a>- 线性结构</h3><h3 id="顺序"><a href="#顺序" class="headerlink" title="- 顺序"></a>- 顺序</h3><h3 id="折半"><a href="#折半" class="headerlink" title="- 折半"></a>- 折半</h3><h3 id="判定树"><a href="#判定树" class="headerlink" title="- 判定树"></a>- 判定树</h3><h3 id="分块"><a href="#分块" class="headerlink" title="- 分块"></a>- 分块</h3><h3 id="树形结构"><a href="#树形结构" class="headerlink" title="- 树形结构"></a>- 树形结构</h3><h3 id="二叉排序树-1"><a href="#二叉排序树-1" class="headerlink" title="- 二叉排序树"></a>- 二叉排序树</h3><h3 id="子主题-1-1"><a href="#子主题-1-1" class="headerlink" title="- 子主题 1"></a>- 子主题 1</h3><h3 id="二叉平衡树"><a href="#二叉平衡树" class="headerlink" title="- 二叉平衡树"></a>- 二叉平衡树</h3><h3 id="B树"><a href="#B树" class="headerlink" title="- B树"></a>- B树</h3><h3 id="插入"><a href="#插入" class="headerlink" title="- 插入"></a>- 插入</h3><h3 id="删除"><a href="#删除" class="headerlink" title="- 删除"></a>- 删除</h3><h3 id="查找-1"><a href="#查找-1" class="headerlink" title="- 查找"></a>- 查找</h3><h3 id="b-树"><a href="#b-树" class="headerlink" title="- b+树"></a>- b+树</h3><h3 id="概念-2"><a href="#概念-2" class="headerlink" title="- 概念"></a>- 概念</h3><h3 id="散列结构"><a href="#散列结构" class="headerlink" title="- 散列结构"></a>- 散列结构</h3><h3 id="性能分析"><a href="#性能分析" class="headerlink" title="- 性能分析"></a>- 性能分析</h3><h3 id="冲突处理"><a href="#冲突处理" class="headerlink" title="- 冲突处理"></a>- 冲突处理</h3><h3 id="平均查找长度-4"><a href="#平均查找长度-4" class="headerlink" title="- 平均查找长度"></a>- 平均查找长度</h3><h3 id="查找成功"><a href="#查找成功" class="headerlink" title="- 查找成功"></a>- 查找成功</h3><h3 id="查找失败"><a href="#查找失败" class="headerlink" title="- 查找失败"></a>- 查找失败</h3><h3 id="ASL-PiCi-1"><a href="#ASL-PiCi-1" class="headerlink" title="- ASL=PiCi+++"></a>- ASL=PiCi+++</h3><h3 id="第七章-排序"><a href="#第七章-排序" class="headerlink" title="### 第七章 排序"></a>### 第七章 排序</h3><h3 id="稳定性"><a href="#稳定性" class="headerlink" title="- 稳定性"></a>- 稳定性</h3><h3 id="时间复杂度-4"><a href="#时间复杂度-4" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="空间复杂度-1"><a href="#空间复杂度-1" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="内部排序"><a href="#内部排序" class="headerlink" title="- 内部排序"></a>- 内部排序</h3><h3 id="插入排序"><a href="#插入排序" class="headerlink" title="- 插入排序"></a>- 插入排序</h3><h3 id="直接插入排序"><a href="#直接插入排序" class="headerlink" title="- 直接插入排序"></a>- 直接插入排序</h3><h3 id="时间复杂度-5"><a href="#时间复杂度-5" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O（n-2）"><a href="#O（n-2）" class="headerlink" title="- O（n^2）"></a>- O（n^2）</h3><h3 id="空间复杂度-2"><a href="#空间复杂度-2" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="O（1）"><a href="#O（1）" class="headerlink" title="- O（1）"></a>- O（1）</h3><h3 id="稳定性-1"><a href="#稳定性-1" class="headerlink" title="- 稳定性"></a>- 稳定性</h3><h3 id="每次插入，从后向前先比较在移动，所以不会出现相同元素相对位置发生变化"><a href="#每次插入，从后向前先比较在移动，所以不会出现相同元素相对位置发生变化" class="headerlink" title="- 每次插入，从后向前先比较在移动，所以不会出现相同元素相对位置发生变化"></a>- 每次插入，从后向前先比较在移动，所以不会出现相同元素相对位置发生变化</h3><h3 id="适用性"><a href="#适用性" class="headerlink" title="- 适用性"></a>- 适用性</h3><h3 id="适用于顺序存储、链式存储的线性表中"><a href="#适用于顺序存储、链式存储的线性表中" class="headerlink" title="- 适用于顺序存储、链式存储的线性表中"></a>- 适用于顺序存储、链式存储的线性表中</h3><h3 id="这般插入排序"><a href="#这般插入排序" class="headerlink" title="- 这般插入排序"></a>- 这般插入排序</h3><h3 id="时间复杂度-6"><a href="#时间复杂度-6" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O-N-2-1"><a href="#O-N-2-1" class="headerlink" title="- O(N^2)"></a>- O(N^2)</h3><h3 id="空间复杂度-3"><a href="#空间复杂度-3" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="减少了比较元素的次数"><a href="#减少了比较元素的次数" class="headerlink" title="- 减少了比较元素的次数"></a>- 减少了比较元素的次数</h3><h3 id="希尔排序"><a href="#希尔排序" class="headerlink" title="- 希尔排序"></a>- 希尔排序</h3><h3 id="时间复杂度-7"><a href="#时间复杂度-7" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O（n-1-3）"><a href="#O（n-1-3）" class="headerlink" title="- O（n^1.3）"></a>- O（n^1.3）</h3><h3 id="空间复杂度-4"><a href="#空间复杂度-4" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="O（1）-1"><a href="#O（1）-1" class="headerlink" title="- O（1）"></a>- O（1）</h3><h3 id="稳定性-2"><a href="#稳定性-2" class="headerlink" title="- 稳定性"></a>- 稳定性</h3><h3 id="不稳定，会改变先后次序"><a href="#不稳定，会改变先后次序" class="headerlink" title="- 不稳定，会改变先后次序"></a>- 不稳定，会改变先后次序</h3><h3 id="交换排序"><a href="#交换排序" class="headerlink" title="- 交换排序"></a>- 交换排序</h3><h3 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="- 冒泡排序"></a>- 冒泡排序</h3><h3 id="时间复杂度-8"><a href="#时间复杂度-8" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="最优"><a href="#最优" class="headerlink" title="- 最优"></a>- 最优</h3><h3 id="比较次数-n-1"><a href="#比较次数-n-1" class="headerlink" title="- 比较次数 n-1"></a>- 比较次数 n-1</h3><h3 id="移动次数0"><a href="#移动次数0" class="headerlink" title="- 移动次数0"></a>- 移动次数0</h3><h3 id="O（n）"><a href="#O（n）" class="headerlink" title="- O（n）"></a>- O（n）</h3><h3 id="最坏"><a href="#最坏" class="headerlink" title="- 最坏"></a>- 最坏</h3><h3 id="比较次数"><a href="#比较次数" class="headerlink" title="- 比较次数"></a>- 比较次数</h3><h3 id="n-n-1-2-1"><a href="#n-n-1-2-1" class="headerlink" title="- n(n-1)/2"></a>- n(n-1)/2</h3><h3 id="移动次数"><a href="#移动次数" class="headerlink" title="- 移动次数"></a>- 移动次数</h3><h3 id="n-n-1-3-2"><a href="#n-n-1-3-2" class="headerlink" title="- n(n-1)*3/2"></a>- n(n-1)*3/2</h3><h3 id="空间复杂度-5"><a href="#空间复杂度-5" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="O（1）-2"><a href="#O（1）-2" class="headerlink" title="- O（1）"></a>- O（1）</h3><h3 id="稳定性-3"><a href="#稳定性-3" class="headerlink" title="- 稳定性"></a>- 稳定性</h3><h3 id="i》j时候不会交换-稳定"><a href="#i》j时候不会交换-稳定" class="headerlink" title="- i》j时候不会交换  稳定"></a>- i》j时候不会交换  稳定</h3><h3 id="快速排序"><a href="#快速排序" class="headerlink" title="- 快速排序"></a>- 快速排序</h3><h3 id="划分"><a href="#划分" class="headerlink" title="- 划分"></a>- 划分</h3><h3 id="过程特征"><a href="#过程特征" class="headerlink" title="- 过程特征"></a>- 过程特征</h3><h3 id="时间复杂度-9"><a href="#时间复杂度-9" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="最好"><a href="#最好" class="headerlink" title="- 最好"></a>- 最好</h3><h3 id="O-nlog2-n"><a href="#O-nlog2-n" class="headerlink" title="- O(nlog2(n))"></a>- O(nlog2(n))</h3><h3 id="最坏-1"><a href="#最坏-1" class="headerlink" title="- 最坏"></a>- 最坏</h3><h3 id="O-n-2"><a href="#O-n-2" class="headerlink" title="- O(n^2)"></a>- O(n^2)</h3><h3 id="空间复杂度-6"><a href="#空间复杂度-6" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="最好-1"><a href="#最好-1" class="headerlink" title="- 最好"></a>- 最好</h3><h3 id="log2-n-1）"><a href="#log2-n-1）" class="headerlink" title="- log2(n+1）"></a>- log2(n+1）</h3><h3 id="最坏-2"><a href="#最坏-2" class="headerlink" title="- 最坏"></a>- 最坏</h3><h3 id="o-n"><a href="#o-n" class="headerlink" title="- o(n)"></a>- o(n)</h3><h3 id="不稳定"><a href="#不稳定" class="headerlink" title="- 不稳定"></a>- 不稳定</h3><h3 id="在快拍中，不产生有序子序列，但每趟排序后会将基准元素放到器最终位置"><a href="#在快拍中，不产生有序子序列，但每趟排序后会将基准元素放到器最终位置" class="headerlink" title="- 在快拍中，不产生有序子序列，但每趟排序后会将基准元素放到器最终位置"></a>- 在快拍中，不产生有序子序列，但每趟排序后会将基准元素放到器最终位置</h3><h3 id="选择排序"><a href="#选择排序" class="headerlink" title="- 选择排序"></a>- 选择排序</h3><h3 id="简单选择排序"><a href="#简单选择排序" class="headerlink" title="- 简单选择排序"></a>- 简单选择排序</h3><h3 id="时间复杂度-10"><a href="#时间复杂度-10" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="O-N-2-2"><a href="#O-N-2-2" class="headerlink" title="- O(N^2)"></a>- O(N^2)</h3><h3 id="移动较少"><a href="#移动较少" class="headerlink" title="- 移动较少"></a>- 移动较少</h3><h3 id="空间复杂度-7"><a href="#空间复杂度-7" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="不稳定-1"><a href="#不稳定-1" class="headerlink" title="- 不稳定"></a>- 不稳定</h3><h3 id="堆排序"><a href="#堆排序" class="headerlink" title="- 堆排序"></a>- 堆排序</h3><h3 id="建堆"><a href="#建堆" class="headerlink" title="- 建堆"></a>- 建堆</h3><h3 id="插入-1"><a href="#插入-1" class="headerlink" title="- 插入"></a>- 插入</h3><h3 id="调整"><a href="#调整" class="headerlink" title="- 调整"></a>- 调整</h3><h3 id="时间复杂度-11"><a href="#时间复杂度-11" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="最坏-3"><a href="#最坏-3" class="headerlink" title="- 最坏"></a>- 最坏</h3><h3 id="O-nog2n"><a href="#O-nog2n" class="headerlink" title="- O(nog2n)"></a>- O(nog2n)</h3><h3 id="子主题-3-1"><a href="#子主题-3-1" class="headerlink" title="- 子主题 3"></a>- 子主题 3</h3><h3 id="空间复杂度-8"><a href="#空间复杂度-8" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="归并排序"><a href="#归并排序" class="headerlink" title="- 归并排序"></a>- 归并排序</h3><h3 id="归并路数"><a href="#归并路数" class="headerlink" title="- 归并路数"></a>- 归并路数</h3><h3 id="时间复杂度-12"><a href="#时间复杂度-12" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="空间复杂度-9"><a href="#空间复杂度-9" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="归并过程"><a href="#归并过程" class="headerlink" title="- 归并过程"></a>- 归并过程</h3><h3 id="时间复杂度-13"><a href="#时间复杂度-13" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="空间复杂度-10"><a href="#空间复杂度-10" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="时间复杂度-14"><a href="#时间复杂度-14" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="单趟归并-O（N）"><a href="#单趟归并-O（N）" class="headerlink" title="- 单趟归并  O（N）"></a>- 单趟归并  O（N）</h3><h3 id="需要-logn趟"><a href="#需要-logn趟" class="headerlink" title="- 需要  logn趟"></a>- 需要  logn趟</h3><h3 id="空间复杂度-11"><a href="#空间复杂度-11" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="辅助空间-n个单元"><a href="#辅助空间-n个单元" class="headerlink" title="- 辅助空间  n个单元"></a>- 辅助空间  n个单元</h3><h3 id="稳定性-4"><a href="#稳定性-4" class="headerlink" title="- 稳定性"></a>- 稳定性</h3><h3 id="不会改变相同关键字记录的次序"><a href="#不会改变相同关键字记录的次序" class="headerlink" title="- 不会改变相同关键字记录的次序"></a>- 不会改变相同关键字记录的次序</h3><h3 id="基数排序"><a href="#基数排序" class="headerlink" title="- 基数排序"></a>- 基数排序</h3><h3 id="时间复杂度-15"><a href="#时间复杂度-15" class="headerlink" title="- 时间复杂度"></a>- 时间复杂度</h3><h3 id="空间复杂度-12"><a href="#空间复杂度-12" class="headerlink" title="- 空间复杂度"></a>- 空间复杂度</h3><h3 id="外部排序"><a href="#外部排序" class="headerlink" title="- 外部排序"></a>- 外部排序</h3><h3 id="多路归并排序"><a href="#多路归并排序" class="headerlink" title="- 多路归并排序"></a>- 多路归并排序</h3><h3 id="分支主题-3"><a href="#分支主题-3" class="headerlink" title="- 分支主题 3"></a>- 分支主题 3</h3><h3 id="-18"><a href="#-18" class="headerlink" title="#"></a>#</h3><h2 id="十：排序"><a href="#十：排序" class="headerlink" title="十：排序"></a>十：排序</h2><h3 id="口诀"><a href="#口诀" class="headerlink" title="口诀"></a>口诀</h3><ul>
<li>希快选堆不稳定，二路归并空杂n，快堆归时杂都一样，除快时杂最坏</li>
<li>折半排序：</li>
<li>希尔排序（分组排序）</li>
</ul>
<h3 id="插入排序-1"><a href="#插入排序-1" class="headerlink" title="插入排序"></a>插入排序</h3><ul>
<li>交换排序</li>
<li><p>冒泡排序</p>
<ul>
<li><p>基本思想</p>
<ul>
<li>通过无序区中相邻元素关键字（关键字指的就是该元素的值）之间比较和位置的交换使关键字最小的元素如气泡一般逐渐往上漂浮，直至水面。</li>
</ul>
</li>
</ul>
</li>
<li><p>快速排序</p>
<ul>
<li><p>基本思想</p>
<ul>
<li>在待排序的n个元素中任取一个元素（通常取第一个元素）作为基准，把该元素放入适当的位置，比它小的元素放在基准元素的左边，比它大的元素放在基准元素的右边。</li>
</ul>
</li>
<li><p>快速排序的划分过程</p>
<ul>
<li>从两头向中间扫描。例如：（6,8,7,9,0,1,3,2,4,5），我们选6作为基准元素，然后从两头向中间扫描，这里只有6的右边这一头，反正从边向中间扫描，第一趟得出两个子区间（5,4,2,3,0,1）和（9,7,8），于是第一趟得到的序列就是（5,4,2,3,0,1,6,9,7,8），注意0和1，按道理是得到（5,4,2,3,1,0）的，但看书上都是倒数第一个和倒数第二个会换位置的。</li>
</ul>
</li>
</ul>
</li>
<li><p>选择排序</p>
<ul>
<li>首先在未排序序列中找到最小（大）元素，存放到排序序列的起始位置，然后，再从剩余未排序元素中继续寻找最小（大）元素，然后放到已排序序列的末尾。以此类推，直到所有元素均排序完毕。最好，最坏，平均时间复杂度都为O(n*log2n)</li>
</ul>
</li>
<li><p>简单选择排序</p>
<ul>
<li>在待排序找出最小的元素，放到有序区</li>
</ul>
</li>
<li><p>堆排序</p>
<ul>
<li>小根堆排序</li>
</ul>
</li>
<li><p>归并排序：</p>
</li>
<li>基数排序：</li>
</ul>
<h2 id="子主题-20"><a href="#子主题-20" class="headerlink" title="子主题 20"></a>子主题 20</h2><h2 id="分支主题-3-1"><a href="#分支主题-3-1" class="headerlink" title="分支主题 3"></a>分支主题 3</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/23/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" data-id="cl403sxsb003pf8vu6r7s3v81" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-五子棋对战之博弈树" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/%E4%BA%94%E5%AD%90%E6%A3%8B%E5%AF%B9%E6%88%98%E4%B9%8B%E5%8D%9A%E5%BC%88%E6%A0%91/" class="article-date">
  <time class="dt-published" datetime="2021-12-20T14:10:02.000Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/notes-on-computer-expertise/2021/12/20/%E4%BA%94%E5%AD%90%E6%A3%8B%E5%AF%B9%E6%88%98%E4%B9%8B%E5%8D%9A%E5%BC%88%E6%A0%91/">五子棋对战之博弈树</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/%E4%BA%94%E5%AD%90%E6%A3%8B%E5%AF%B9%E6%88%98%E4%B9%8B%E5%8D%9A%E5%BC%88%E6%A0%91/" data-id="cl403sxqk000bf8vuft9621ak" data-title="五子棋对战之博弈树" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/九、File和IO流" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E4%B9%9D%E3%80%81File%E5%92%8CIO%E6%B5%81/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:40:50.822Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="九、File和IO流"><a href="#九、File和IO流" class="headerlink" title="九、File和IO流"></a>九、File和IO流</h2><h3 id="2-File类常用的方法"><a href="#2-File类常用的方法" class="headerlink" title="2.File类常用的方法"></a>2.File类常用的方法</h3><h3 id="4-java流的分类"><a href="#4-java流的分类" class="headerlink" title="4.java流的分类"></a>4.java流的分类</h3><h3 id="5-文本文件的读写"><a href="#5-文本文件的读写" class="headerlink" title="5.文本文件的读写"></a>5.文本文件的读写</h3><ul>
<li>用FileInputStream和FileOutputStream读写文本文件</li>
<li>用BufferedReader和BufferedWriter读写文本文件</li>
</ul>
<h3 id="6-二进制文件的读写"><a href="#6-二进制文件的读写" class="headerlink" title="6.二进制文件的读写"></a>6.二进制文件的读写</h3><ul>
<li>使用DataInputStream和DataOutputStream读写二进制文件</li>
</ul>
<h3 id="7-InputStream类常用方法"><a href="#7-InputStream类常用方法" class="headerlink" title="7.InputStream类常用方法"></a>7.InputStream类常用方法</h3><ul>
<li>int read( )</li>
<li>int read(byte[] b)</li>
<li>int read(byte[] b,int off,int len)</li>
<li>void close( )</li>
<li>int available()</li>
<li>FileInputStream(File file)</li>
<li>FileInputStream(String name)</li>
</ul>
<h3 id="8-OutputStream类常用方法"><a href="#8-OutputStream类常用方法" class="headerlink" title="8.OutputStream类常用方法"></a>8.OutputStream类常用方法</h3><ul>
<li>void write(int c)</li>
<li>void write(byte[] buf)</li>
<li>void write(byte[] b,int off,int len)</li>
<li>void close( )</li>
<li>FileOutputStream (File file)</li>
<li>FileOutputStream(String name)</li>
<li>FileOutputStream(String name,boolean append)</li>
</ul>
<h3 id="9-Writer类常用方法"><a href="#9-Writer类常用方法" class="headerlink" title="9.Writer类常用方法"></a>9.Writer类常用方法</h3><ul>
<li>write(String str)</li>
<li>write(String str,int off,int len)</li>
<li>void close()</li>
<li>void flush()</li>
<li>BufferedReader(Writer out)</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E4%B9%9D%E3%80%81File%E5%92%8CIO%E6%B5%81/" data-id="cl403sxqx000yf8vu5f90h5i3" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/八、多线程" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E5%85%AB%E3%80%81%E5%A4%9A%E7%BA%BF%E7%A8%8B/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:40:40.956Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="八、多线程"><a href="#八、多线程" class="headerlink" title="八、多线程"></a>八、多线程</h2><h3 id="1-进程"><a href="#1-进程" class="headerlink" title="1.进程:"></a>1.进程:</h3><ul>
<li>在内存中开辟了一块空间，供程序运行</li>
<li>一个进程表示一个程序的运行。</li>
<li>一个程序可以开多个进程。</li>
</ul>
<h3 id="2-线程："><a href="#2-线程：" class="headerlink" title="2.线程："></a>2.线程：</h3><ul>
<li>是程序运行中最小的单位。</li>
<li>一个进程可以有多个线程，但至少有一个线程。</li>
<li>进程中执行运算的最小单位，可完成一个独立的顺序控制流程</li>
</ul>
<h3 id="3-实现多线程的两种方式："><a href="#3-实现多线程的两种方式：" class="headerlink" title="3.实现多线程的两种方式："></a>3.实现多线程的两种方式：</h3><ul>
<li><p>1，写一个类继承Thread</p>
<ul>
<li>重写run();方法</li>
<li>通过start();启动线程</li>
<li>如果调用run方法，那么就只有一个main线程</li>
</ul>
</li>
<li><p>2，实现 Runable接口</p>
<ul>
<li>重写run();方法</li>
<li>通过代理模式运行start();启动线程</li>
</ul>
</li>
</ul>
<h3 id="4-设置线程运行的优先级："><a href="#4-设置线程运行的优先级：" class="headerlink" title="4.设置线程运行的优先级："></a>4.设置线程运行的优先级：</h3><ul>
<li>setPriority(10) </li>
<li>Thread.MAX_PRIORITY Thread.MIN_PRIORITY</li>
<li>优先级高的线程会获得更多的运行机会。</li>
</ul>
<h3 id="5-synchronized"><a href="#5-synchronized" class="headerlink" title="5.synchronized"></a>5.synchronized</h3><ul>
<li><p>同步锁 </p>
<ul>
<li>当多个线程对象操纵同一资源时，要使用synchronized关键字来进行资源的的同步处理，可以使用同步方法和同步代码块来实现。</li>
</ul>
</li>
</ul>
<h3 id="6"><a href="#6" class="headerlink" title="6."></a>6.</h3><ul>
<li><p>StringBuffer </p>
<ul>
<li><p>线程安全 </p>
<ul>
<li>效率低</li>
</ul>
</li>
</ul>
</li>
<li><p>StringBuilder </p>
<ul>
<li><p>线程不安全 </p>
<ul>
<li>效率高</li>
</ul>
</li>
</ul>
</li>
<li><p>HashTable </p>
<ul>
<li><p>线程安全 </p>
<ul>
<li>效率低</li>
</ul>
</li>
</ul>
</li>
<li><p>HashMap </p>
<ul>
<li><p>线程不安全 </p>
<ul>
<li>效率高</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="7-线程睡眠"><a href="#7-线程睡眠" class="headerlink" title="7.线程睡眠"></a>7.线程睡眠</h3><ul>
<li>sleep()方法使线程转到阻塞状态</li>
</ul>
<h3 id="8-线程强制运行"><a href="#8-线程强制运行" class="headerlink" title="8.线程强制运行"></a>8.线程强制运行</h3><ul>
<li>join()方法使当前线程暂停执行，等待调用该方法的线程结束后再继续执行本线程。</li>
</ul>
<h3 id="9-线程礼让"><a href="#9-线程礼让" class="headerlink" title="9.线程礼让"></a>9.线程礼让</h3><ul>
<li>yield()方法、暂停当前正在执行的线程对象，把执行机会让给相同的或者更高优先级的线程。</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E5%85%AB%E3%80%81%E5%A4%9A%E7%BA%BF%E7%A8%8B/" data-id="cl403sxqx000zf8vu92oqbcre" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十五章SSM整合案例【企业权限管理系统】" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%BA%94%E7%AB%A0SSM%E6%95%B4%E5%90%88%E6%A1%88%E4%BE%8B%E3%80%90%E4%BC%81%E4%B8%9A%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E3%80%91/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:38:33.068Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十五章SSM整合案例【企业权限管理系统】"><a href="#第三十五章SSM整合案例【企业权限管理系统】" class="headerlink" title="第三十五章SSM整合案例【企业权限管理系统】"></a>第三十五章SSM整合案例【企业权限管理系统】</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%BA%94%E7%AB%A0SSM%E6%95%B4%E5%90%88%E6%A1%88%E4%BE%8B%E3%80%90%E4%BC%81%E4%B8%9A%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E3%80%91/" data-id="cl403sxr3001af8vu5yxj9jie" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十四章Maven高级" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E5%9B%9B%E7%AB%A0Maven%E9%AB%98%E7%BA%A7/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:38:23.793Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十四章Maven高级"><a href="#第三十四章Maven高级" class="headerlink" title="第三十四章Maven高级"></a>第三十四章Maven高级</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E5%9B%9B%E7%AB%A0Maven%E9%AB%98%E7%BA%A7/" data-id="cl403sxr20018f8vu0xhefgki" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十三章Oracle" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%B8%89%E7%AB%A0Oracle/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:38:16.648Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十三章Oracle"><a href="#第三十三章Oracle" class="headerlink" title="第三十三章Oracle"></a>第三十三章Oracle</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%B8%89%E7%AB%A0Oracle/" data-id="cl403sxr00016f8vucfry11l3" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十二章SpringMVC" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%BA%8C%E7%AB%A0SpringMVC/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:38:00.248Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十二章SpringMVC"><a href="#第三十二章SpringMVC" class="headerlink" title="第三十二章SpringMVC"></a>第三十二章SpringMVC</h2><h3 id="Unit1springmvc"><a href="#Unit1springmvc" class="headerlink" title="Unit1springmvc"></a>Unit1springmvc</h3><ul>
<li><p>1概述</p>
<ul>
<li><p>1.1spring mvc简介</p>
<ul>
<li>Spring MVC框架是有一个MVC框架，通过实现Model-View-Controller模式来很好地将数据、业务与展现进行分离。从这样一个角度来说，Spring MVC和Struts、Struts2非常类似。Spring MVC的设计是围绕DispatcherServlet展开的，DispatcherServlet负责将请求派发到特定的handler。通过可配置的handler mappings、view resolution、locale以及theme resolution来处理请求并且转到对应的视图。</li>
</ul>
</li>
<li><p>1.2springmvc的核心组件和执行流程</p>
<ul>
<li>DispatcherServlet，这个Servlet会接受所有的请求，是整个框架的控制中心，负责整体执行逻辑的控制,它会将具体的工作交由具体的其他组件来实现。</li>
<li>HandlerMapping，这个组件用来注册和查询url和处理器映射关系，即DispatcherServlet接受到了一个请求后，听过这个组件来决定使用哪个handler来处理。</li>
<li>HandlerAdapter，这个组件用来适配各种各样的handler形式，比如实现Controller接口形式的处理器，实现HttpRequestHandler接口形式的处理器，使用@RequestMapping注解的方法，甚至另外一个servlet。</li>
<li>Handler，就是我们实现的控制器。</li>
<li>ModelAndView，这个组件用来封装模型数据和视图。</li>
<li>ViewResolver，视图解析器，用来将一个视图名称解析成一个view对象</li>
<li>View 视图,其作用是将模型数据和视图模板渲染出来，并输出到response中。</li>
<li><p>一次HTTP请求的旅行:</p>
<ul>
<li>客户端发起HTTP请求到servlet容器，如tomcat，servlet容器将请求交到DispatchServlet去处理</li>
<li>DispatchServlet拿到请求后，解析出请求的url，然后找HandlerMapping去获取这个请求要处理的handler。</li>
<li>HandlerMapping返回HandlerExecutionChain，它会封装具体的handler和拦截器</li>
<li>DispatchServlet通过handler去找对应的HandlerAdapter</li>
<li>调用HandlerAdapter，其内部会调用具体的handler，执行具体的业务逻辑</li>
<li>HandlerAdapter获取具体的handler执行结果，返回ModelAndView</li>
<li>DispatchServlet获取HandlerAdapter返回的ModelAndView</li>
<li>DispatchServlet通过ModelAndView去找ViewResolver解析出一个真实的view对象（逻辑视图到实际视图）</li>
<li>DispatchServlet获取解析出来的View对象</li>
<li>DispatchServlet通过View去渲染response返回结果。</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="子主题-2"><a href="#子主题-2" class="headerlink" title="子主题 2"></a>子主题 2</h3><h3 id="项目1-稻草问答"><a href="#项目1-稻草问答" class="headerlink" title="项目1 稻草问答"></a>项目1 稻草问答</h3><ul>
<li><p>1稻草问答项目搭建</p>
<ul>
<li><p>1.1稻草问答项目</p>
<ul>
<li><p>介绍:知识问答系统,目的是为了及时解决学员在线学习遇到的各类问题.此系统采用互联网架构。利用Redis缓存数据，利用ES提供查询性能，利用Kafka消除并发都赛，分布式微服务技术提升并发性能</p>
<ul>
<li><p>功能</p>
<ul>
<li>学员     登录      讲师</li>
<li>提问   回复</li>
<li>提问评论</li>
<li>相关提问</li>
<li>我的提问 任务</li>
<li>收藏</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>1.2项目部署结构</p>
</li>
<li>1.3原型</li>
<li><p>1.4项目搭建</p>
<ul>
<li><p>项目结构</p>
<ul>
<li><p>Straw-common</p>
<ul>
<li>通用参数</li>
</ul>
</li>
<li><p>Straw-config</p>
<ul>
<li>配置管理</li>
</ul>
</li>
<li><p>Straw-eureka-server</p>
<ul>
<li>注册服务</li>
</ul>
</li>
<li><p>Straw-gateway</p>
<ul>
<li>网关服务</li>
</ul>
</li>
<li><p>Straw-model</p>
<ul>
<li>实体模型</li>
</ul>
</li>
<li><p>Straw-portal</p>
<ul>
<li>门户入口</li>
</ul>
</li>
<li><p>Straw-search</p>
<ul>
<li>搜索</li>
</ul>
</li>
<li><p>Straw-search-api</p>
<ul>
<li>搜索API</li>
</ul>
</li>
</ul>
</li>
<li><p>1.4.1straw-portal搭建</p>
<ul>
<li><p>用spring web组件创建模块</p>
<ul>
<li><p>配置strawpom文件</p>
<ul>
<li>&lt;?xml version=”1.0” encoding=”UTF-8”?&gt;<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>straw</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>straw-portal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>straw-portal</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>1.5部署前段原型</p>
<ul>
<li>1.5.1下载网站原型</li>
<li><p>1.5.2部署项目</p>
<ul>
<li><p>配置strawportal pom文件</p>
<ul>
<li>&lt;?xml version=”1.0” encoding=”UTF-8”?&gt;<br><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><br><modelVersion>4.0.0</modelVersion><br><parent><br><groupId>cn.tedu</groupId><br><artifactId>straw</artifactId><br><version>0.0.1-SNAPSHOT</version><br><relativePath/> <!-- lookup parent from repository -->
</parent><br><groupId>cn.tedu</groupId><br><artifactId>straw-portal</artifactId><br><version>0.0.1-SNAPSHOT</version><br><name>straw-portal</name><br><description>Demo project for Spring Boot</description><properties>
<java.version>1.8</java.version>
</properties>

</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><dependencies><br>  <dependency></p>
<pre><code>  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
</code></pre><p>  &lt;/dependency&gt;<br>  <dependency></p>
<pre><code>  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
</code></pre><p>  &lt;/dependency&gt;<br>  <dependency></p>
<pre><code>  &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
  &lt;artifactId&gt;lombok&lt;/artifactId&gt;
</code></pre><p>  &lt;/dependency&gt;<br>&lt;/dependencies&gt;<br>&lt;/project&gt;</p>
<ul>
<li>1.5.3启动springboot测试</li>
</ul>
</li>
</ul>
</li>
<li><p>2稻草问答业务功能分析</p>
<ul>
<li><p>2.1软件分析和设计思路</p>
<ul>
<li><p>分析软件功能，搞清楚业务流转过程</p>
<ul>
<li><p>找出软件中的业务实体，根据实体设计类和数据表，找到数据结构</p>
<ul>
<li>根据业务流程设计软件功能明便携软件代码，编写计算方法</li>
</ul>
</li>
<li><p>2.2概要分析</p>
<ul>
<li>用户管理模块：登录，注册，权限管理</li>
<li>用户问答模块：提问，回答问题，讨论，收藏</li>
<li>后台管理模块：用户管理，系统维护</li>
</ul>
</li>
<li><p>2.3数据结构设计</p>
<ul>
<li><p>Answer</p>
<ul>
<li>| id             | int         | NO   | PRI | NULL    | auto_increment |</li>
<li>| content        | longtext    | NO   |     | NULL    |                |</li>
<li>| user_id        | int         | NO   |     | NULL    |                |</li>
<li>| user_nick_name | varchar(20) | NO   |     | NULL    |                |</li>
<li>| question_id    | int         | NO   |     | NULL    |                |</li>
<li>| is_accepted    | int         | NO   |     | NULL    |                |</li>
<li>| gmt_create     | datetime    | YES  |     | NULL    |                |</li>
<li>| gmt_modified   | datetime    | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>class_info</p>
<ul>
<li>| id           | int          | NO   | PRI | NULL    | auto_increment |</li>
<li>| name         | varchar(30)  | NO   |     | NULL    |                |</li>
<li>| invite_code  | varchar(255) | NO   |     | NULL    |                |</li>
<li>| is_enabled   | tinyint      | NO   |     | NULL    |                |</li>
<li>| gmt_create   | datetime     | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime     | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>user</p>
<ul>
<li>| id           | int         | NO   | PRI | NULL    | auto_increment |</li>
<li>| username     | varchar(20) | YES  | UNI | NULL    |                |</li>
<li>| nick_name    | varchar(20) | YES  |     | NULL    |                |</li>
<li>| password     | char(68)    | NO   |     | NULL    |                |</li>
<li>| gender       | int         | YES  |     | NULL    |                |</li>
<li>| day_of_birth | date        | YES  |     | NULL    |                |</li>
<li>| phone        | varchar(20) | YES  | UNI | NULL    |                |</li>
<li>| class_id     | int         | YES  |     | NULL    |                |</li>
<li>| is_enabled   | int         | YES  |     | NULL    |                |</li>
<li>| is_locked    | int         | YES  |     | NULL    |                |</li>
<li>| account_type | int         | YES  |     | NULL    |                |</li>
<li>| gmt_create   | datetime    | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime    | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>comment</p>
<ul>
<li>| id             | int         | NO   | PRI | NULL    | auto_increment |</li>
<li>| user_id        | int         | NO   |     | NULL    |                |</li>
<li>| user_nick_name | varchar(20) | NO   |     | NULL    |                |</li>
<li>| answer_id      | int         | NO   |     | NULL    |                |</li>
<li>| content        | text        | NO   |     | NULL    |                |</li>
<li>| gmt_create     | datetime    | YES  |     | NULL    |                |</li>
<li>| gmt_modified   | datetime    | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>permission</p>
<ul>
<li>| id           | int          | NO   | PRI | NULL    | auto_increment |</li>
<li>| authority    | varchar(255) | NO   |     | NULL    |                |</li>
<li>| description  | varchar(255) | YES  |     | NULL    |                |</li>
<li>| gmt_create   | datetime     | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime     | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>question</p>
<ul>
<li>| id             | int          | NO   | PRI | NULL    | auto_increment |</li>
<li>| title          | varchar(100) | NO   |     | NULL    |                |</li>
<li>| content        | longtext     | NO   |     | NULL    |                |</li>
<li>| user_id        | int          | NO   |     | NULL    |                |</li>
<li>| user_nick_name | varchar(20)  | NO   |     | NULL    |                |</li>
<li>| status         | int          | NO   |     | NULL    |                |</li>
<li>| hits           | int          | NO   |     | NULL    |                |</li>
<li>| tag_ids        | varchar(255) | YES  |     | NULL    |                |</li>
<li>| gmt_create     | datetime     | YES  |     | NULL    |                |</li>
<li>| gmt_modified   | datetime     | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>question_tag</p>
<ul>
<li>| id           | int      | NO   | PRI | NULL    | auto_increment |</li>
<li>| tag_id       | int      | NO   |     | NULL    |                |</li>
<li>| question_id  | int      | NO   |     | NULL    |                |</li>
<li>| gmt_create   | datetime | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>role</p>
<ul>
<li>| id           | int          | NO   | PRI | NULL    | auto_increment |</li>
<li>| name         | varchar(255) | NO   |     | NULL    |                |</li>
<li>| gmt_create   | datetime     | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime     | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>role_permission</p>
<ul>
<li>| id            | int      | NO   | PRI | NULL    | auto_increment |</li>
<li>| role_id       | int      | NO   |     | NULL    |                |</li>
<li>| permission_id | int      | NO   |     | NULL    |                |</li>
<li>| gmt_create    | datetime | YES  |     | NULL    |                |</li>
<li>| gmt_modified  | datetime | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>tag</p>
<ul>
<li>| id           | int          | NO   | PRI | NULL    | auto_increment |</li>
<li>| name         | varchar(255) | NO   |     | NULL    |                |</li>
<li>| created_user | varchar(255) | NO   |     | NULL    |                |</li>
<li>| gmt_create   | datetime     | YES  |     | NULL    |                |</li>
<li>| gmt_modified | datetime     | YES  |     | NULL    |                |</li>
</ul>
</li>
<li><p>user_question</p>
</li>
<li>user_role</li>
</ul>
</li>
<li><p>2.4初始化数据库</p>
<ul>
<li>创建数据表</li>
<li>插入数据</li>
</ul>
</li>
</ul>
</li>
<li><p>3用lombok简化开发</p>
<ul>
<li><p>3.1Lombok介绍：</p>
<ul>
<li>Lombok项目是一个Java库，它会自动插入编辑器和构建工具中，Lombok提供了一组有用的注释，用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净，简洁且易于维护的Java类。</li>
</ul>
</li>
<li><p>3.2Lombok安装</p>
<ul>
<li>File-》settings》lombok插件</li>
</ul>
</li>
<li><p>3.3Lombok库依赖</p>
<ul>
<li><dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</li>
</ul>
</li>
<li><p>3.4Lombok常用注解</p>
<ul>
<li>@Setter ：注解在类或字段，注解在类时为所有字段生成setter方法，注解在字段上时只为该字段生成setter方法。</li>
<li>@Getter ：使用方法同上，区别在于生成的是getter方法。</li>
<li>@ToString ：注解在类，添加toString方法。</li>
<li>@EqualsAndHashCode： 注解在类，生成hashCode和equals方法。</li>
<li>@NoArgsConstructor： 注解在类，生成无参的构造方法。</li>
<li>@RequiredArgsConstructor： 注解在类，为类中需要特殊处理的字段生成构造方法，比如final和被@NonNull注解的字段。</li>
<li>@AllArgsConstructor： 注解在类，生成包含类中所有字段的构造方法。</li>
<li>@Data： 注解在类，生成setter/getter、equals、canEqual、hashCode、toString方法，如为final属性，则不会为该属性生成setter方法。</li>
<li>@Slf4j： 注解在类，生成log变量，严格意义来说是常量</li>
</ul>
</li>
<li><p>3.5测试</p>
<ul>
<li><p>3.5.1创建一个msg类型</p>
<ul>
<li>@Data<br>public class Msg {<br>private int id;<br>private String name;<br>private String text;<br>}</li>
</ul>
</li>
<li><p>3.5.2编写测试案例，测试是否生成方法</p>
<ul>
<li>public class TestCase {<br>@Test<br>public void testMsg()<br>{<br>Msg msg=new Msg();<br>msg.setId(1);<br>msg.setName(“234”);<br>msg.setText(“hello”);<br>System.out.println(msg);<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>}</p>
<pre><code>        - 3.6slf4j

            - 3.6.1创建一个loggerDemo类型

                - @Slf4j
</code></pre><p>public class LoggerDemo {<br>    public  LoggerDemo()<br>    {<br>        log.debug(“hello world!”);<br>    }<br>}</p>
<pre><code>            - 3.6.2编写测试案例，测试是否生成方法

                - @Test
</code></pre><p>public void testLogger() {<br>    LoggerDemo demo = new LoggerDemo();<br>}</p>
<pre><code>        - 3.7MyBatis Plus简化MyBatis

            - 3.7.1概述

                - MyBatis-Plus (opens new window)（简称 MP）是一个 MyBatis (opens new window)的增强工具，在 MyBatis 的基础上只做增强不做改变，为简化开发、提高效率而生。

            - 3.7.2依赖版本

                - 父

                    - &lt;dependencyManagement&gt;
&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
        &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
        &lt;version&gt;3.3.1&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;
</code></pre><p>&lt;/dependencyManagement&gt;</p>
<pre><code>                - 子

                    - &lt;dependency&gt;
&lt;groupId&gt;com.baomidou&lt;/groupId&gt;
&lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
</code></pre><p>&lt;/dependency&gt;</p>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<pre><code>            - 3.7.3 代码

                - 1.声明实体类User

                    - @Data
</code></pre><p>public class User {<br>    private Integer id;<br>    private String username;<br>    private String nick_name;<br>    private String password;<br>    private String gender;<br>    private LocalDate day_of_birth;<br>    private String phone;<br>    private Integer class_id;<br>    private Boolean is_enabled;<br>    private Boolean account_type;<br>    private LocalDate gmt_create;<br>    private LocalDate gmt_modified;<br>}</p>
<pre><code>                - 2.定义数据访问接口

                    - @Repository
</code></pre><p>public interface UserMapper extends BaseMapper<User> {</p>
<p>}</p>
<pre><code>                - 3.在启动类开启MaPPer接口扫描功能

                    - @MapperScan(&quot;cn.tedu.straw.portal.mapper&quot;)

                - 4.配置application.properties增加数据库参数，以及MyBAtisMapper日志

                    - spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
</code></pre><p>spring.datasource.url=jdbc:mysql://localhost:3306/straw?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone = GMT&amp;allowPublicKeyRetrieval=true&amp;nullCatalogMeansCurrent=true<br>spring.datasource.username=root<br>spring.datasource.password=123456</p>
<pre><code>            - 3.7.4 测试（MapperTest）

                - @Test
</code></pre><p>public void testUserMapper() {<br>    User user = userMapper.selectById(1);<br>    System.out.println(user);<br>}</p>
<pre><code>        - 3.8代码生成器

            - 3.8.1依赖文件

                - &lt;dependency&gt;
&lt;groupId&gt;com.baomidou&lt;/groupId&gt;
&lt;artifactId&gt;mybatis-plus-extension&lt;/artifactId&gt;
&lt;version&gt;3.3.1&lt;/version&gt;
</code></pre><p>&lt;/dependency&gt;</p>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.3.1</version>
</dependency>

<pre><code>            - 3.8.2编写usercontroller

                - @RestController
</code></pre><p>@RequestMapping(“/portal/user”)<br>public class UserController {<br>    @Autowired<br>    IUserService userService;<br>    //<a target="_blank" rel="noopener" href="http://localhost:8080/portal/user/get?id=1">http://localhost:8080/portal/user/get?id=1</a><br>    @GetMapping(“/get”)<br>    /<em><br>    如果登录用户有、user/get权限 才能执行
     </em>/<br>    public User get(int id)<br>    {<br>        User user=userService.getById(id);<br>        return user;<br>    }<br>}</p>
<pre><code>    - 4spring安全框架

        - 4.1什么是spring安全框架

            - Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架；它提供了一组可以在 Spring 应用上下文中配置的 Bean，充分利用了 Spring IoC， DI 和 AOP 功能，为应用系统提供声明式的安全访问控制功能，减少了为企业系统安全控制编写大量重复代码的工作。

        - 4.2 spring安全框架的依赖

            - 子

                - &lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
&lt;version&gt;1.3.0.RELEASE&lt;/version&gt;
</code></pre><p>&lt;/dependency&gt;</p>
<pre><code>            - 配置文件

                - spring.security.user.name=admin
                - spring.security.user.password=123456

        - 4.3密码加密

            - 单向散列算法Bcrypt

                - 代码

                    - //创建一个类作为配置文件，添加@Configration注解，使用@Bean注解配置
</code></pre><p>@Configuration<br>@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解<br>public class SecurityConfig extends WebSecurityConfigurerAdapter {<br>    //@Bean<br>    //public PasswordEncoder passwordEncoder()<br>    //{<br>    //    return new BCryptPasswordEncoder();<br>    //}<br>    //@Autowired<br>    //UserDetailsServiceImpl userDetailsService;</p>
<pre><code>@Override
protected void configure(AuthenticationManagerBuilder auth)throws Exception
&#123;
    super.configure(auth);
    /*
    添加一个测试用户 tom 密码123456 权限/user/get

    auth.inMemoryAuthentication().withUser(&quot;Tom&quot;)
        .password(&quot;&#123;bcrypt&#125;$2a$10$4WxQNiXb/gIcWc/8XiRqXOpR.0NoXlJnkTgI7FaM8rzm6ExH7C622&quot;)
        .authorities(&quot;/user/get&quot;,&quot;/user/list&quot;);
    auth.userDetailsService(userDetailsService);*/
&#125;

@Override
protected void configure(HttpSecurity http) throws Exception
&#123;
    http.csrf().disable().authorizeRequests()
        .antMatchers(
                &quot;/login.html&quot;,
                &quot;/register.html&quot;,
                &quot;/register&quot;,
                &quot;/js/*&quot;,
                &quot;/img/*&quot;,
                &quot;/css/*&quot;,
                &quot;/browser_components/**&quot;
        ).permitAll()
        .anyRequest().authenticated()
        .and().formLogin()
        .loginPage(&quot;/login.html&quot;)
        .loginProcessingUrl(&quot;/login&quot;)
        .failureUrl(&quot;/login.html?error&quot;)
        .defaultSuccessUrl(&quot;/index.html&quot;)
        .and().logout()
        .logoutUrl(&quot;/logout&quot;)
        .logoutSuccessUrl(&quot;/login.html?logout&quot;);
&#125;
</code></pre><p>}</p>
<pre><code>        - 4.4使用权限控制资源

            - 用途

                - 添加测试用户信息，并为用户分配权限

            - 代码

                - @Configuration
</code></pre><p>@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解<br>public class SecurityConfig extends WebSecurityConfigurerAdapter {<br>@Override<br>protected void configure(AuthenticationManagerBuilder auth)throws Exception<br>{<br>    //super.configure(auth);<br>    //添加一个测试用户 tom 密码123456 权限/user/get<br>    auth.inMemoryAuthentication().withUser(“Tom”)<br>        .password(“{bcrypt}$2a$10$4WxQNiXb/gIcWc/8XiRqXOpR.0NoXlJnkTgI7FaM8rzm6ExH7C622”)<br>        .authorities(“/user/get”,”/user/list”);<br>    //auth.userDetailsService(userDetailsService);*/<br>}</p>
<pre><code>        - 4.5利用数据库登录

            - 业务流程

                - 用户
                - userDetailServiceImpl
                - userServiceImpl
                - UserMapper
                - 数据库

            - 第一步 编写sql语句

                - select u.username,r.name,p.authority &quot; +
    &quot;from user u &quot; +
    &quot;left join user_role ur on u.id = ur.user_id &quot; +
    &quot;left join role r on r.id = ur.role_id &quot; +
    &quot;left join role_permission rp on r.id = rp.role_id &quot; +
    &quot;left join permission p on p.id = rp.permission_id &quot; +
    &quot;where u.id=#&#123;userId&#125;&quot;

            - 第二步 编写代码

                - @Override
</code></pre><p>protected void configure(AuthenticationManagerBuilder auth)throws Exception<br>{<br>    auth.userDetailsService(userDetailsService);<br>}</p>
<pre><code>                - 测试

                    - @Test
</code></pre><p>public void findUserByUsername()<br>{<br>    User user=userMapper.findUserByUsername(“admin”);<br>    System.out.println(user);<br>}</p>
<p>@Test<br>public void findUserPermissionById()<br>{<br>    List<Permission> list=userMapper.findUserPermissionById(1);<br>    for(Permission p:list)<br>    {<br>        System.out.println(p);<br>    }<br>}</p>
<pre><code>            - 在IUserService接口中声明功能方法，获取用户详细信息

                - public interface IUserService extends IService&lt;User&gt; &#123;
UserDetails getUserDetails(String username);
</code></pre><p>}</p>
<pre><code>            - 实现该方法

                - public class UserServiceImpl extends ServiceImpl&lt;UserMapper, User&gt; implements IUserService &#123;
@Autowired
UserMapper userMapper;
@Override
public UserDetails getUserDetails(String username) &#123;
    System.out.println(username);
    User user = userMapper.findUserByUsername(username);
    System.out.println(user);
    if (user == null)
        return null;
    List&lt;Permission&gt; permissions = userMapper.findUserPermissionById(user.getId());
    String[] arr = new String[permissions.size()];
    /*int i = 0;
    for (Permission p : permissions) &#123;
        arr[i++] = p.getAuthority();
        System.out.println(p);
    &#125;
    List&lt;Role&gt; roles = userMapper.findUserRolesById(user.getId());
    arr = Arrays.copyOf(arr, arr.length + roles.size());
    for (Role role : roles)
        arr[i++] = role.getName();*/
    UserDetails u = org.springframework.security.core.userdetails.User.builder()
                                                                      .username(user.getUsername())
                                                                      .password(user.getPassword())
                                                                      .authorities(arr)
                                                                      .build();
    System.out.println(u);

    return u;
&#125;
</code></pre><p>}</p>
<pre><code>                - 测试

                    - @Autowired
IUserService userService;
@Test
private void getUserDetails()
&#123;
    UserDetails user=userService.getUserDetails(&quot;admin&quot;);
    System.out.println(user);
&#125;
</code></pre><p>}</p>
<pre><code>        - 4.6控制授权范围

            - @Override
</code></pre><p>protected void configure(HttpSecurity http) throws Exception<br>{<br>    http.csrf().disable().authorizeRequests()<br>        .antMatchers(<br>                “/login.html”,<br>                “/register.html”,<br>                “/register”,<br>                “/js/<em>“,<br>                “/img/</em>“,<br>                “/css/<em>“,<br>                “/browser_components/*</em>“<br>        ).permitAll()<br>        .anyRequest().authenticated()<br>        .and().formLogin()<br>        .loginPage(“/login.html”)<br>        .loginProcessingUrl(“/login”)<br>        .failureUrl(“/login.html?error”)<br>        .defaultSuccessUrl(“/index.html”)<br>        .and().logout()<br>        .logoutUrl(“/logout”)<br>        .logoutSuccessUrl(“/login.html?logout”);</p>
<p>}</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%BA%8C%E7%AB%A0SpringMVC/" data-id="cl403sxr10017f8vu5q796nul" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十一章Spring" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%B8%80%E7%AB%A0Spring/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:37:41.334Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十一章Spring"><a href="#第三十一章Spring" class="headerlink" title="第三十一章Spring"></a>第三十一章Spring</h2><h3 id="unit1-Spring-IOC"><a href="#unit1-Spring-IOC" class="headerlink" title="unit1 Spring-IOC"></a>unit1 Spring-IOC</h3><ul>
<li><p>1 spring框架简介</p>
<ul>
<li><p>1.1 spring是什么</p>
<ul>
<li>Spring框架是一个开放源代码的J2EE应用程序框架，由Rod Johnson发起，是针对bean的生命周期进行管理的轻量级容器（lightweight container）。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题，提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序，也可以和Struts、Webwork、Tapestry等众多Web框架组合使用，并且可以与 Swing等桌面应用程序AP组合。因此， Spring不仅仅能应用于JEE应用程序之中，也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成，分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。</li>
<li>轻量级：与EJB相比，依赖资源少，消耗资源少</li>
<li><p>核心功能</p>
<ul>
<li>IOC/DI：控制反转依赖注入</li>
<li>AOP：面向切面编程</li>
</ul>
</li>
</ul>
</li>
<li><p>1.2IOC</p>
<ul>
<li><p>主动控制</p>
<ul>
<li>有应用程序主动控制管理对象组件，适合管理创建过程简单得对象</li>
</ul>
</li>
<li><p>控制反转</p>
<ul>
<li>由外部容器环境创建管理对象组件交给应用程序使用，是和管理创新过程复杂得对象，从对象使用者的角度看是简单的</li>
</ul>
</li>
<li><p>第一个测试程序</p>
<ul>
<li>public class Demo {<br>@Override<br>public String toString()<br>{<br>return “Hello World”;<br>}<br>}</li>
<li>@Configuration<br>public class Config {<br>@Bean<br>/**<ul>
<li>告诉spring在启动时候，加载被@Bean标注得方法</li>
<li>返回值是Spring创建得对象，方法名是Bean得ID<br>*/<br>public Demo bean()<br>{<br>return new Demo();<br>}<br>}</li>
</ul>
</li>
<li>public class DemoApplication {</li>
</ul>
</li>
</ul>
<p>public static void main(String[] args) {<br>  //SpringApplication.run(DemoApplication.class, args);<br>  AnnotationConfigApplicationContext ctx =</p>
<pre><code>      new AnnotationConfigApplicationContext(Config.class);
</code></pre><p>  Demo demo = ctx.getBean(“bean”, Demo.class);<br>  System.out.println(demo);<br>}</p>
</li>
</ul>
</li>
</ul>
<p>}</p>
<pre><code>- 1.3 Java Bean
</code></pre><ul>
<li><p>2利用JUnit测试</p>
<ul>
<li><p>2.1使用junit</p>
<ul>
<li><p>在test编写测试案例</p>
<ul>
<li>public class TestCase {<br>@Test<br>public void test()<br>{<br>System.out.println(“Hello World”);<br>}<br>}</li>
</ul>
</li>
<li><p>测试</p>
<ul>
<li>Hello World</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Process finished with exit code 0</p>
<pre><code>- 2.2利用junit测试Spring

    - 代码

        - public class TestCase &#123;
AnnotationConfigApplicationContext ctx;

@Before
public void init() &#123;
    ctx = new AnnotationConfigApplicationContext(Config.class);
    System.out.println(&quot;初始化spring&quot;);
&#125;

@After
public void destroy() &#123;
    ctx.close();
    System.out.println(&quot;销毁spring&quot;);
&#125;

@Test
public void testBean() &#123;
    Demo demo = ctx.getBean(&quot;bean&quot;, Demo.class);
    System.out.println(demo);
&#125;

    - 测试

        - 初始化spring
</code></pre><p>Hello World<br>09:57:14.413 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@61d47554, started on Thu May 27 09:57:13 CST 2021<br>销毁spring</p>
<ul>
<li><p>3组件扫描</p>
<ul>
<li><p>3.1spring组件扫描功能</p>
<ul>
<li>Spring提供组件扫描注解,利用组件爱你扫描注解和组件注解配合,可以自动扫描包空间创造bean对象,减少编码,提高效率</li>
<li><p>1.使用组件@Component注解声明类</p>
<ul>
<li>@Component// spring在组件扫描时候回找到标注componet<br>//将类创建为对象 并其bean id为demobean<br>public class DemoBean implements Serializable<br>{<br>@Override<br>public String toString()<br>{<br>return “DemoBean”;<br>}<br>}</li>
</ul>
</li>
<li><p>2.在配置类注明扫描</p>
<ul>
<li>@ComponentScan(basePackages = “com.example.junit”)</li>
</ul>
</li>
<li><p>3.测试</p>
<ul>
<li>@Test<br>public  void testDeanBean()<br>{<br>//测试组件扫描<br>DemoBean bean=ctx.getBean(“demoBean”,DemoBean.class);<br>System.out.println(bean);<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>3.2spring提供多种组件扫描</p>
<ul>
<li>@Controller 控制器组件</li>
<li>@Service业务层组件</li>
<li>@Component通用组件</li>
<li><p>测试:编写被扫描的组件</p>
<ul>
<li>@Controller<br>public class DemoController implements Serializable{<br>@Override<br>public String toString()<br>{<br>return “DemoController”;<br>}<br>}<br>@Service<br>public class DemoService implements Serializable{<br>@Override<br>public String toString()<br>{<br>return “DemoService”;<br>}<br>}</li>
</ul>
</li>
<li><p>测试</p>
<ul>
<li>@Test<br>public void DemoController()<br>{<br>/<em><br>测试利用controller创建bean组件
</em>/<br>DemoController controller=ctx.getBean(“demoController”,DemoController.class);<br>System.out.println(controller);<br>}<br>@Test<br>public void DemoService()<br>{<br>/<em><br>测试利用controller创建bean组件
</em>/<br>DemoService service=ctx.getBean(“demoService”, DemoService.class);<br>System.out.println(service);<br>}</li>
</ul>
</li>
</ul>
</li>
<li><p>3.3自定义组件id</p>
<ul>
<li>在使用组件扫描功能时候@Component注解可以添加属性，自定义组件id</li>
</ul>
</li>
</ul>
</li>
<li><p>4.spring bean的管理</p>
<ul>
<li><p>4.1bean作用域</p>
<ul>
<li>@Test<br>public void testSingleton()<br>{<br>/<em><br>默认情况，spring单利管理对象
</em>/<br>DemoBean b1=ctx.getBean(“demoBean”,DemoBean.class);<br>DemoBean b2=ctx.getBean(“demoBean”,DemoBean.class);<br>System.out.println(b1==b2);<br>}<br>@Test<br>public void testPrototype()<br>{<br>/<em><br>测试：原型、<br>每次获取的都是一个新实例
</em>/<br>ExampleBean b1=ctx.getBean(“exampleBean”,ExampleBean.class);<br>ExampleBean b2=ctx.getBean(“exampleBean”,ExampleBean.class);<br>System.out.println(b1==b2);<br>}</li>
</ul>
</li>
<li><p>4.2对象生命周期</p>
<ul>
<li>管理方式：</li>
<li><p>2声明bean组件类型</p>
<ul>
<li>@Component<br>public class FileLogger {<br>public PrintWriter out;<br>@PostConstruct<br>public void open() throws IOException<br>{<br>out=new PrintWriter(“Z:\\Demo.txt”);<br>System.out.println(“open demo”);<br>}<br>@PreDestroy<br>public void close()<br>{<br>out.close();;<br>System.out.println(“close demo”);<br>}</li>
</ul>
</li>
</ul>
<p>@Configuration<br>public static class Config {<br>  @Bean<br>  /<em><br>  告诉spring在启动时候加重被bean标注的方法
   </em>/<br>  public Demo bean()<br>  {</p>
<pre><code>  return new Demo();
</code></pre><p>  }<br>}<br>}</p>
<ul>
<li><p>测试</p>
<ul>
<li>@Test<br>public void testFileLogger()<br>{<br>/*<br>测试spring对象生命周期管理功能<br>spring创建时候bean对象自动执行初始化方法<br>spring关闭时候销毁对象</li>
</ul>
</li>
</ul>
<p>*/<br>FileLogger logger=ctx.getBean(“fileLogger”,FileLogger.class);<br>logger.out.println(“dddd”);<br>logger.out.println(“dddd”);<br>}</p>
<pre><code>  - @Test
</code></pre><p>public void testDemoLogger()<br>{<br>/<em><br>测试 bean对象生命周期管理功能
</em>/<br>DemoLogger logger=ctx.getBean(“demoLogger”,DemoLogger.class);<br>logger.out.println(“dddd”);<br>logger.out.println(“dddd”);<br>}</p>
</li>
<li><p>4.3懒惰初始化</p>
<ul>
<li><p>1定义bean组件    </p>
<ul>
<li>//懒惰初始化<br>@Component<br>@Lazy<br>public class Person {<br>public Person()<br>{<br>System.out.println(“创建Person”);<br>}<br>@Override<br>public  String toString()<br>{return “Tom”;}<br>}</li>
</ul>
</li>
<li><p>2.测试</p>
<ul>
<li>@Test<br>public void testPerson()<br>{<br>/<em><br>测试：懒惰初始化
</em>/<br>Person person=ctx.getBean(“person”,Person.class);<br>System.out.println(person);<br>}</li>
</ul>
</li>
<li><p>1定义bean组件</p>
<ul>
<li>public class Student {<br>public  Student()<br>{<br>System.out.println(“create student”);<br>}<br>@Override<br>public String toString()<br>{<br>return “Andy”;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>}</p>
<pre><code>    - 2.测试

        - public void testStudent()
</code></pre><p>{<br>    Student student=ctx.getBean(“student”,Student.class);<br>    System.out.println(student);<br>    System.out.println(“OK”);<br>}</p>
<pre><code>- 4.4@Import导入配置

    - 1.定义一个配置类SysConfig 其中配置一个Date类型的bean组件 id为MyDate

        - /**
</code></pre><ul>
<li><p>系统管理模块配置信息<br>*/<br>public class SysConfig {<br> @Bean<br> public Date myDate() {</p>
<pre><code> return new Date();
</code></pre><p> }<br>}</p>
<pre><code> - 2.在主配置类利用impoort引入sysconfig

     - @Configuration
</code></pre><p>@ComponentScan(basePackages = “com.example.junit”)<br>@Import({com.example.junit.SysConfig.class})<br>public class Config {</p>
<pre><code> - 3.测试

     - @Test
</code></pre><p>public  void testMyDate()<br>{<br> Date date=ctx.getBean(“myDate”,Date.class);<br> System.out.println(date);<br>}</p>
</li>
</ul>
<h3 id="Unit2-springDI"><a href="#Unit2-springDI" class="headerlink" title="Unit2 springDI"></a>Unit2 springDI</h3><ul>
<li><p>1依赖注入</p>
<ul>
<li><p>1.1什么是依赖注入</p>
<ul>
<li>依赖注入。 依赖注入让bean与bean之间以配置文件组织在一起，而不是以硬编码的方式耦合在一起。</li>
</ul>
</li>
<li><p>1.2bean注入</p>
<ul>
<li><p>案例：模拟光头强砍树</p>
<ul>
<li><p>1.创建saw</p>
<ul>
<li>@Component<br>public class Saw implements Serializable {<br>private String name=”铁连菊”;<br>@Override<br>public String toString()<br>{<br>return name;<br>}<br>}</li>
</ul>
</li>
<li><p>2.创建worker</p>
<ul>
<li>@Component<br>public class Saw implements Serializable {<br>private String name=”铁连菊”;<br>@Override<br>public String toString()<br>{<br>return name;<br>}<br>}</li>
</ul>
</li>
<li><p>3.创建配置文件</p>
<ul>
<li>//spring会自动根据变量类型匹配主键<br>//如果匹配 就将beam注入<br>@Configuration<br>public class Config {<br>@Bean<br>public Saw saw()<br>{<br>return new Saw();<br>}<br>@Bean<br>public Worker worker(Saw saw)<br>{<br>Worker worker=new Worker();<br>worker.saw=saw;<br>return worker;<br>}<br>}</li>
</ul>
</li>
<li><p>4.测试</p>
<ul>
<li>public class test {<br>AnnotationConfigApplicationContext ctx;<br>@Before<br>public void init()<br>{<br>ctx=new AnnotationConfigApplicationContext(Config.class);<br>}<br>@After<br>public void destroy()<br>{<br>ctx.close();<br>}<br>@Test<br>public void testWorker()<br>{<br>Worker worker=ctx.getBean(“worker”,Worker.class);<br>worker.work();<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>1.3@Autowired</p>
</li>
<li><p>1.4同时使用@bean@compont</p>
<ul>
<li><p>案例 bean声明的组件注入到component声明的组件</p>
<ul>
<li><p>1利用bean配置类config声明组件</p>
<ul>
<li>@Configuration<br>@ComponentScan(“com.example.druid”)<br>public class Config {<br>@Bean<br>public Date currentDate()<br>{<br>return new Date();<br>}<br>}</li>
</ul>
</li>
<li><p>利用component声明组件引入date类型</p>
<ul>
<li>@Component<br>public class Employee {</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>private String name=”Tom”;<br>@Autowired<br>private Date date;<br>@Override<br>public String toString()<br>{<br>  return “Employee [name=”+name+”, date=”+date+”]”;<br>}<br>}</p>
<pre><code>  - 3.测试

      - public void testEmployee()
</code></pre><p>{<br>Employee employee=ctx.getBean(“employee”,Employee.class);<br>System.out.println(employee);<br>}</p>
<ul>
<li><p>声明component声明的组件注入到bean</p>
<ul>
<li><p>1.声明bean类型</p>
<ul>
<li>public class Dept {<br>private String name;<br>private Employee manager;<br>public void setManager(Employee manager)<br>{<br>this.manager=manager;<br>}<br>@Override<br>public String toString()<br>{<br>return “Dept [name=”+name+”, manager=”+manager+”]”;<br>}<br>}</li>
</ul>
</li>
<li><p>2.在配置类config中利用bean声明bean组件</p>
<ul>
<li>@Bean<br>public Dept dept(Employee employee)<br>{<br>Dept dept=new Dept();<br>dept.setManager(employee);<br>return  dept;<br>}</li>
</ul>
</li>
<li><p>3.测试</p>
<ul>
<li>@Test<br>public void testDept()<br>{<br>Dept dept=ctx.getBean(“dept”,Dept.class);<br>System.out.println(dept);<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>3.使用properties文件</p>
<ul>
<li><p>3.1druid连接池</p>
<ul>
<li><p>思路：</p>
<ul>
<li>1利用maven导入druid连接池api和mysql数据库驱动api</li>
<li>2将连接池作为javabean在config。Java中配置</li>
<li>3 测试连接池是否可用</li>
</ul>
</li>
<li><p>例子</p>
<ul>
<li><p>1.导入连接池</p>
<ul>
<li><dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</li>
</ul>
</li>
<li><p>2.配置config</p>
<ul>
<li>@Bean<br>public DataSource dataSource()<br>{<br>DruidDataSource ds =new DruidDataSource();<br>ds.setDriverClassName(“com.mysql.cj.jdbc.Driver”);<br>ds.setUrl(“jdbc:mysql://localhost:3306/db1?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone = GMT&amp;allowPublicKeyRetrieval=true”);<br>ds.setUsername(“root”);<br>ds.setPassword(“123456”);<br>ds.setMaxActive(10);<br>ds.setInitialSize(2);<br>return ds;<br>}</li>
</ul>
</li>
<li><p>测试</p>
<ul>
<li>@Test<br>public void testDataSource()<br>{<br>String sql=”select ‘hello world’”;<br>DataSource ds=ctx.getBean(“dataSource”,DataSource.class);<br>try(Connection conn=ds.getConnection())<br>{<br>Statement st=conn.createStatement();<br>ResultSet rs=st.executeQuery(sql);<br>while (rs.next())<br>{<br>System.out.println(rs.getString(1));<br>}<br>}<br>catch (Exception e)<br>{<br>e.printStackTrace();<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>3.2@P{ropertySource和environment</p>
<ul>
<li><p>程序参数保存到properties文件，spring提供注解用于读取properties，保存到environment中</p>
<ul>
<li>db.driver=com.mysql.cj.jdbc.Driver<br>db.url=jdbc:mysql://localhost:3306/db1?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone = GMT&amp;allowPublicKeyRetrieval=true<br>db.username=root<br>db.password=123456<br>db.maxActive=10<br>db.initialSize=2<br>@Autowired<br>Environment env;</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>@Bean<br>public DataSource dataSource2()<br>{<br>    DruidDataSource ds=new DruidDataSource();<br>    ds.setDriverClassName(env.getProperty(“db.driver”));<br>    ds.setUrl(env.getProperty(“db.url”));<br>    ds.setUsername(env.getProperty(“db.username”));<br>    ds.setPassword(env.getProperty(“db.password”));<br>    ds.setMaxActive(env.getProperty(“db.maxActive”,Integer.class));<br>    ds.setInitialSize(env.getProperty(“db.initialSize”,Integer.class));<br>    return ds;<br>}<br>@Test<br>public void testDataSource2()<br>{<br>    String sql=”select ‘hello world’”;<br>    DataSource ds=ctx.getBean(“dataSource2”,DataSource.class);<br>    try(Connection conn=ds.getConnection())<br>    {<br>        Statement st=conn.createStatement();<br>        ResultSet rs=st.executeQuery(sql);<br>        while (rs.next())<br>        {<br>            System.out.println(rs.getString(1));<br>        }<br>    }<br>    catch (Exception e)<br>    {<br>        e.printStackTrace();<br>    }<br>}</p>
<pre><code>- 3.3value

    - 利用value读取当前系统环境environment的信息，注入到变量

        - @Bean
</code></pre><p>public DataSource dataSource3(<br>        @Value(“${db.drive}”) String driver,<br>        @Value(“${db.url}”) String url,<br>        @Value(“${db.username}”) String username,<br>        @Value(“${db.password}”) String password,<br>        @Value(“${db.maxActive}”) int maxActive,<br>        @Value(“${db.initialSize}”) int initialSize)<br>{<br>    DruidDataSource ds =new DruidDataSource();<br>    ds.setDriverClassName(driver);<br>    ds.setUrl(url);<br>    ds.setUsername(username);<br>    ds.setPassword(password);<br>    ds.setMaxActive(maxActive);<br>    ds.setInitialSize(initialSize);<br>    return ds;<br>}</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E4%B8%80%E7%AB%A0Spring/" data-id="cl403sxr00015f8vufb5l7i2f" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Java/第三十章Mybatis" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E7%AB%A0Mybatis/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:37:33.863Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第三十章Mybatis"><a href="#第三十章Mybatis" class="headerlink" title="第三十章Mybatis"></a>第三十章Mybatis</h2>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%B8%89%E5%8D%81%E7%AB%A0Mybatis/" data-id="cl403sxr20019f8vuedsl3g30" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/notes-on-computer-expertise/page/6/">&laquo; Prev</a><a class="page-number" href="/notes-on-computer-expertise/">1</a><span class="space">&hellip;</span><a class="page-number" href="/notes-on-computer-expertise/page/5/">5</a><a class="page-number" href="/notes-on-computer-expertise/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/notes-on-computer-expertise/page/8/">8</a><a class="page-number" href="/notes-on-computer-expertise/page/9/">9</a><span class="space">&hellip;</span><a class="page-number" href="/notes-on-computer-expertise/page/14/">14</a><a class="extend next" rel="next" href="/notes-on-computer-expertise/page/8/">Next &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C#工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C++工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/Mysql/">Mysql</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/blender/">blender</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/linux/">linux</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/manim/">manim</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/spring/">spring</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C/">vba基础操作</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E5%88%9B%E9%80%A0%E6%A8%A1%E5%BC%8F/">创造模式</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">操作系统基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/">操作系统开发</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E5%AD%A6/">数学</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">数据结构基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%A8%A1%E6%9D%BF/">模板</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">深度学习</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%8B%B1%E8%AF%AD/">英语</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%99%9A%E5%B9%BB4/">虚幻4</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86/">计算机组成原理</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/">计算机网络</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/notes-on-computer-expertise/tags/C/" rel="tag">C++</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/notes-on-computer-expertise/tags/C/" style="font-size: 10px;">C++</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/05/">May 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/03/">March 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/02/">February 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/01/">January 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2021/12/">December 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/31/vue/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E9%AA%8C%E8%AF%81%E7%A0%81%E6%97%A0%E6%B3%95%E6%98%BE%E7%A4%BA/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/26/%E6%95%B0%E6%8D%AE%E5%BA%93/navicat%E5%AE%89%E8%A3%85/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/25/%E8%99%9A%E5%B9%BB4%E5%BC%95%E6%93%8E%E5%BC%80%E5%8F%91/%E8%99%9A%E5%B9%BB%E5%9B%9B%20mod%E5%88%B6%E4%BD%9C/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/python/python%E6%89%B9%E9%87%8F%E7%94%9F%E6%88%90%E6%95%B0%E6%8D%AE/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E7%AC%94%E8%AE%B0/EXCEL%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/notes-on-computer-expertise/" class="mobile-nav-link">Home</a>
  
    <a href="/notes-on-computer-expertise/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/notes-on-computer-expertise/js/jquery-3.4.1.min.js"></script>



  
<script src="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.js"></script>




<script src="/notes-on-computer-expertise/js/script.js"></script>





  </div>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</body>
</html>